Java 相干的基础知识
一:Java 接口和抽象类
面对对象语言设计的重点在于形象,Java接口(interface)和抽象类(abstract class)代表的就是形象类型,就是咱们须要提出的形象层的具体表现。
OOP面向对象的编程,如果要进步程序的复用率,减少程序 的可维护性,可扩展性,就必须是面向接口的编程,面向形象的编程,正确地应用接口、抽象类这些有用的形象类型作为你构造档次上的顶层。
形象办法abstract void fun();
形象办法必须用 abstract关键词润饰,一个类中含有形象办法,则这个类为抽象类,抽象类必须在类前用abstract关键字润饰
(1)有形象办法的类肯定是抽象类,抽象类不肯定有形象办法
(2)抽象类中的形象办法的修饰符只能为public或者protected,默认为public;
抽象类
public abstract class TestAb{
public TestAb(){
//抽象类构造方法
System.out.println("我是抽象类,我不能间接实例化,但能够被子类实例化呦");
}
//这是形象办法
public abstract void fun();
//我是非形象办法
pub void watch(){
System.out.println("我是非形象办法");
}
}
//子类继承了抽象类
public class ChildTestAb extends TestAb{
public ChildTestAb (){
//形象子类构造方法
System.out.println("我是形象子类,我能够实例化");
}
@Override
public void fun() {
}
}
//应用,能够实例化类
TestAb childTestAb=new ChildTestAb();
(1)因为抽象类中含有无具体实现的办法,所以不能用抽象类创建对象(不能间接new TestAb())
(2)一个子类继承一个抽象类,则子类必须实现父类形象办法,否则子类也必须定义为抽象类;
(3)抽象类能够蕴含属性、办法、构造方法,然而构造方法不能用于实例化,主要用途是被子类调用。
接口
public interface ComputerConfigBuilder {
int a=10;//默认:public static final int a=10;
void setCPU();//定义接口的办法等价于public abstract void setCPU();
void setMemery();
void setHardDisk();
//JDK1.8新个性,容许接口增加非形象办法的实现,定义了default的办法能够不被实现子类所实现,但只能被实现子类的对象调用
//如果子类实现了多个接口,并且这些接口蕴含一样的默认办法,则子类必须重写默认办法
default void sayHello(){
System.out.println("Hello World");
}
}
(1)接口能够蕴含变量和办法(变量:默认变量被隐士指定为public static final,办法:默认成指定为public abstract)
(2)一个类能够实现多个接口
(3)接口不能有构造方法
二:面对对象的三大个性
继承,封装,多态
继承是所有OOP语言不可短少的局部,在java中应用extends关键字来示意继承关系。当创立一个类时,总是在继承,如果没有明确指出要继承的类,就总是隐式地从根类Object进行继承。比方上面这段代码:
class Person{
//构造方法
public Person(){
}
}
//继承,Man继承Person
class Man extends Person{
//构造方法
public Man(){
}
}
Java 只容许单继承,但能够多层继承,一个类能够被多个类继承,也就是一个类能够领有多个子类
留神:
变量
1.子类继承父类的成员变量,可能继承父类的public 和protected成员变量,不可能继承父类的private成员变量
2.如果子类和父类在同一个包下,则子类可能继承,否则子类不可能继承
3.对于子类能够继承的父类成员变量,如果在子类中呈现了同名称的成员变量,则会产生暗藏景象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中拜访父类中同名成员变量,须要应用super关键字来进行援用。
办法
4.子类继承父类的办法,可能继承父类的public和protected成员办法;不可能继承父类的private成员办法;
5.对于父类的包拜访权限成员办法,如果子类和父类在同一个包下,则子类可能继承;否则,子类不可能继承;
6.对于子类能够继承的父类成员办法,如果在子类中呈现了同名称的成员办法,则称为笼罩,即子类的成员办法会笼罩掉父类的同名成员办法。如果要在子类中拜访父类中同名成员办法,须要应用super关键字来进行援用。
构造方法
7.子类是不可能继承父类的结构器,然而要留神的是,如果父类的结构器都是带有参数的,则必须在子类的结构器中显示地通过super关键字调用父类的结构器并配以适当的参数列表。如果父类有无参结构器,则在子类的结构器中用super关键字调用父类结构器不是必须的,如果没有应用super关键字,零碎会主动调用父类的无参结构器
那么这样一看继承有一个关键词super很值得器重,那super到底是什么?
super
super 能够了解为是指向本人父类对象的一个指针,而这个父类指的是离本人最近的一个父类
super次要两种用法:
1.super.成员变量/super.成员办法
2.super(参数。。。):调用父类中某个构造方法
与之区别还有this关键字
this
this 是本身的一个对象,代表对象自身,能够了解为指向对象自身的一个指针
1.形参和成员名字重名,用this 辨别
class Person {
private int age = 10;
public Person(){
System.out.println("初始化年龄:"+age);
}
public int GetAge(int age){
this.age = age;
return this.age;
}
}
2.援用构造函数
//this 常常的应用办法
public class GoodsSortView extends LinearLayout{
public GoodsSortView(Context context) {
this(context, null);//这个是调用本类2个参数的构造方法
}
public GoodsSortView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);//这个是调用本类的三个参数的构造方法
}
public GoodsSortView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);//这个是调用父类的构造方法
}
}
封装:是把过程和数据包围起来,对数据的拜访只能通过已定义的接口。在java中通过关键字private实现封装
封装靠这些拜访修饰符来管制拜访
private 在以后类中可拜访
default(默认) 在以后包内和拜访
protected 在以后类和它派生的类中可拜访
public 公众的拜访权限,谁都能拜访
public class AccreditBean {
private int AccountType;//这种成员变量是公有的,本类能够拜访,内部拜访就,用过get(),set()办法提供相当于接口来拜访这个成员变量,这就是对数据的封装
private String MemberName;
private String NickName;
public int getAccountType() {
return AccountType;
}
public void setAccountType(int accountType) {
AccountType = accountType;
}
public String getMemberName() {
return MemberName;
}
public void setMemberName(String memberName) {
MemberName = memberName;
}
public String getNickName() {
return NickName;
}
public void setNickName(String nickName) {
NickName = nickName;
}
}
多态:
多态指容许不同类的对象对同一音讯做出响应。即同一音讯能够依据发送对象的不同而采纳多种的行为形式(发送音讯就是函数调用)
多态:打消类型之间的耦合关系
多态存在的三个必要条件
1.要有继承
2.要有重写
3.父类援用指向子类对象
例如:List<String> list=new ArrayList<>();平时用的汇合就是多态的体现
事实事物常常会体现出多种状态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即呈现两种状态。
Java作为面向对象的语言,同样能够形容一个事物的多种状态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
多态体现为父类援用变量能够指向子类对象。
多态的转型分为向上转型和向下转型两种
向上转型:多态自身就是向上转型过的过程
应用格局:父类类型 变量名=new 子类类型();
实用场景:当不须要面对子类类型时,通过进步扩展性,或者应用父类的性能就能实现相应的操作。
向下转型:一个曾经向上转型的子类对象能够应用强制类型转换的格局,将父类援用类型转为子类援用各类型
应用格局:子类类型 变量名=(子类类型) 父类类型的变量;
例如:
父类Animal
class Animal {
int num = 10;//成员变量
static int age = 20;//动态成员变量
//成员办法
public void eat() {
System.out.println("动物吃饭");
}
//静态方法
public static void sleep() {
System.out.println("动物在睡觉");
}
public void run(){
System.out.println("动物在奔跑");
}
}
子类Cat
//子类继承了父类,重写了父类的办法
class Cat extends Animal {
int num = 80;
static int age = 90;//动态变量
String name = "tomCat";
//重写父类的办法
public void eat() {
System.out.println("猫吃饭");
}
//子类的静态方法
public static void sleep() {
System.out.println("猫在睡觉");
}
//子类本人的办法
public void catchMouse() {
System.out.println("猫在抓老鼠");
}
}
调用:
//向上转型:父类类型 变量名=new 子类类型();父类援用指向子类对象
Animal am = new Cat();
am.eat();//调用子类成员办法
am.sleep();//静态方法
am.run();//子类没有的办法
System.out.println(am.num);
System.out.println(am.age);
后果:
子类Cat重写了父类Animal的非动态成员办法am.eat();的输入后果为:猫吃饭。
子类重写了父类(Animal)的动态成员办法am.sleep();的输入后果为:动物在睡觉
未被子类(Cat)重写的父类(Animal)办法am.run()输入后果为:动物在奔跑
那么咱们能够依据以上状况总结出多态成员拜访的特点:
成员变量
编译看右边(父类),运行看右边(父类)
成员办法
编译看右边(父类),运行看左边(子类)。动静绑定
静态方法
编译看右边(父类),运行看右边(父类)。
(动态和类相干,算不上重写,所以,拜访还是右边的)
只有非动态的成员办法,编译看右边,运行看左边
多态向上转型有什么弊病了?
Animal am = new Cat();
am.eat();//调用子类成员办法
am.sleep();//静态方法
am.run();//子类没有的办法
System.out.println(am.num);
System.out.println(am.age);
//上面这是2个子类的成员办法和成员变量调用,后果是报错
//am.catchMouse();
//System.out.println(am.name);
起因就是多态的弊病,就是:不能应用子类特有的成员属性和子类特有的成员办法。
如果咱们非要调用子类的成员变量和成员办法呢,
那咱们就能够把这个父类援用指向了子类对象的家伙am再强制变回Cat类型。这样am就是Cat类型的援用了,指向的也是Cat对象了,天然也能应用Cat类的所有属性和所有的成员办法。
Animal am = new Cat();
am.eat();//调用子类成员办法
am.sleep();//静态方法
am.run();//子类没有的办法
System.out.println(am.num);
System.out.println(am.age);
Cat ct = (Cat)am;
ct.eat();
ct.sleep();
ct.run();
ct.catchMouse();
执行强转语句Cat ct = (Cat)am;这个就是向下转型
三:Java外部类
在Java中,能够将一个类定义在另一个类外面或者一个办法外面,这样的类称为外部类。宽泛意义上的外部类一般来说包含这四种:成员外部类、部分外部类、匿名外部类和动态外部类。
1.成员外部类
public class Circle {
double radius=0;
public Circle(double radius){
this.radius=radius;
}
//成员外部类
class Draw{
public void drawShape(){
//能够拜访外部类的成员办法和成员变量,包含动态的属性和办法
System.out.println("画图");
}
}
}
外部类能够领有private拜访权限、protected拜访权限、public拜访权限及包拜访权限
下面是包拜访权限
调用:
// 形式一
//创立外部类对象
Circle circle=new Circle(12);
//创立外部类对象
Circle.Draw draw=circle.new Draw();
//调用外部类办法
draw.drawShape();
//形式二:
new Circle(12).new Draw().drawShape();
如果成员外部类Inner用private润饰,则只能在外部类的外部拜访,如果用public润饰,则任何中央都能拜访;如果用protected润饰,则只能在同一个包下或者继承外部类的状况下拜访;如果是默认拜访权限,则只能在同一个包下拜访
public class Circle {
double radius=0;
public Circle(double radius){
this.radius=radius;
//即只能拜访,通过new Draw()对象拜访办法
new Draw().drawShape();
}
//成员外部类,应用private修饰符润饰的话,只能在外部类内拜访
private class Draw{
public void drawShape(){
System.out.println("画图");
}
}
}
2.部分外部类
部分外部类是定义在一个办法或者一个作用域外面的类,它和成员外部类的区别在于部分外部类的拜访仅限于办法内或者该作用域内。
public class Circle {
double radius=0;
public Circle(double radius){
this.radius=radius;
}
public void draw(){
//部分外部类拜访修饰符,什么都不能写,private,public,protected都不能润饰
class MyDraw{
public void drawShape(){
System.out.println("画图");
}
}
new MyDraw().drawShape();
}
只能办法内调用
内部调用: new Circle(12).draw();
3.匿名外部类
匿名外部类应该是平时咱们编写代码时用得最多的,在编写事件监听的代码时应用匿名外部类岂但不便,而且使代码更加容易保护。上面这段代码是一段Android事件监听代码:
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//这里new OnClickListener
}
}
就是匿名外部类的应用。代码中须要给按钮设置监听器对象,应用匿名外部类可能在实现父类或者接口中的办法状况下同时产生一个相应的对象,然而前提是这个父类或者接口必须先存在能力这样应用。
匿名外部类是惟一一种没有结构器的类。正因为其没有结构器,所以匿名外部类的应用范畴十分无限,大部分匿名外部类用于接口回调。
4.动态外部类
动态外部类也是定义在另一个类外面的类,只不过在类的后面多了一个关键字static。动态外部类是不须要依赖于外部类的,这点和类的动态成员属性有点相似,并且它不能应用外部类的非static成员变量或者办法,这点很好了解,因为在没有外部类的对象的状况下,能够创立动态外部类的对象,如果容许拜访外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
public class Circle {
double radius = 0;
private static String aa = "我是外部类的动态成员变量";
public Circle(double radius) {
this.radius = radius;
//构造方法中调用动态外部类的办法
//在外部类中调用
new Draw().drawShape();
}
private void draw() {
//我是外部类的非静态方法
System.out.println("我是外部类的非静态方法");
//在外部类中调用外部类的属性和办法
Draw.go();//能够通过动态外部类的全类名来调用动态外部类的静态方法(外部类名.动态外部类名.办法)
Draw.d=1; //能够通过动态外部类的全类名来调用动态外部类的动态属性(外部类名.动态外部类名.属性)
//Draw.drawShape();//不能通过类动态外部类的全类名来调用外部类的非动态属性和办法
Draw draw=new Draw();
draw.drawShape();
draw.c=2;////能够通过创立外部类实例来调用动态外部类的非动态属性和办法
}
public static void draw2() {
//我是外部类的静态方法
System.out.println("我是外部类的静态方法");
}
//动态外部类,同样如果加权限pirvate的话,非外部类的内部就不能拜访了
public static class Draw {
private int c;
private static int d;
public Draw() {
}
public static void go(){
System.out.println("我是外部类的静态方法");
}
public void drawShape() {
System.out.println("画图");
//System.out.println(radius);//不能间接拜访外部类的非动态成员变量
System.out.println(aa);
//draw();不能间接拜访外部类的非动态成员办法
draw2();
//然而能够通过创立外部类实例拜访
Circle circle=new Circle();
circle.draw(); //能够通过创立外部类实例来调用外部类的非静态方法
circle.radius=12; //能够通过创立外部类实例来调用外部类的非动态属性
}
}
}
调用:
// 在非外部类中:外部类名.外部类名 name = new 外部类名.外部类名();
Circle.Draw draw= new Circle.Draw();
draw.drawShape();
这里提到了关键词static
static关键字的作用(润饰类、办法、变量、动态块)
static润饰的类只能为外部类,一般类无奈用static关键字润饰(static润饰的外部类相当于一个一般的类,拜访形式为(new 外部类名.外部类的办法() )
static润饰静态方法的拜访形式为 (类名.办法名: Draw.go();)
static润饰的变量为动态变量,动态变量在内存中只有一份存储空间,动态变量不属于某个实例对象,被一个类中的所有对象所共享,属于类,所以也叫类变量,能够间接通过类名来援用。
static关键字加载程序问题:
- 初始化父类的动态代码块…
- 初始化子类动态代码块…
- 10//动态变量
- 初始化父类的构造方法…
- 初始化子类构造方法…
- 一般办法…
总结:
1.动态函数是能够调用类名或者对象进行调用的,而非动态函数只能应用对象进行调用。
2.动态的函数能够间接拜访动态的成员,然而不能间接拜访非动态的成员。
起因:动态函数是能够应用类名间接调用的,这时候可能还没有存在对象,
而非动态的 成员数据是随着对象 的存在而存在的。
-
非动态的函数是能够间接拜访动态与非动态的成员。
起因:非动态函数只能由对象调用,当对象存在的时候,静态数据老早就曾经存在了,而非静态数据也随着对象的创立而存在了。
4.动态函数不能呈现this或者super关键字。
起因:因为动态的函数是能够应用类名调用的,一旦应用类名调用这时候不存在对象,而this关键字是代表了一个函数 的调用者对象,这时候产生了抵触。
四:==和equals区别
对于根本数据类型(byte,short,char,int,float,double,long,boolean)比拟的是值
对于援用数据类型,有equals和==两种办法比拟
==比拟的是援用,比拟援用的地址值,equals办法,是object中的办法,如果不进行重写的话,比拟的也是援用的地址值,理论和==一样。(但 String Integer等对equals重写了,比拟的是值)
JVM把内存划分成两种:一种是栈内存,一种是堆内存。
- 在函数中定义的一些根本类型的变量和对象的援用变量(变量名)都在函数的栈内存中调配。
- 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会主动开释掉为该变量所调配的内存空间,该内存空间能够立刻被另作他用。
- 堆内存用来寄存由new创立的对象(包含由根本类型包装起来的类:Integer、String、Double,实际上每个根本类型都有他的包装类)和数组。
五:浅析Java中的final关键字
在Java中,final关键字能够用来润饰类、办法和变量(包含成员变量和局部变量)
1.润饰类
当用final润饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就能够用final进行润饰。
2.润饰办法
如果只有在想明确禁止 该办法在子类中被笼罩的状况下才将办法设置为final的。(即该办法不能被子类重写)
3.润饰变量
对于一个final变量,如果是根本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是援用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
END: 回避事实的人,将来将更不现实
发表回复