面向对象:封装,继承,多态
类:相关属性和行为的集合。 对象:该类的具体体现
成员变量和局部变量的区别:
位置:成员变量在类中方法外;局部变量在方法定义中或者方法声明上。
内存中的位置:成员变量在堆内存;局部变量在栈内存。
生命周期:成员变量随着对象的创建而存在,随着对象的消失而消失;局部变量随着方法的调用而存在,随着方法的调用完毕而消失
初始化值:成员变量有默认初始化值;局部变量没有默认初始化值,必须定义,赋值,然后才能使用。
匿名对象:仅仅只调用一次的时候,匿名对象调用完就是垃圾,可以被GC回收
用法:匿名对象可以直接调用方法,也可以作为实际参数传递
封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方法。提高代码复用性,提高代码安全性。
原则:将不需要对外提供的内容隐藏起来。把属性隐藏,提供公共方法对其访问。
private关键字:被private修饰的成员变量或成员方法只能在本类中访问。
this关键字:当前类的对象引用
构造方法:给对象的数据进行初始化,方法名与类名相同,没有返回值类型,没有返回值。
创建对象做了哪写事情:Student s = new Student();
把Student.class文件加载到内存
在栈内存给s变量开辟一个空间
在堆内存为学生对象申请一个空间
给成员变量进行默认初始化
给成员变量进行显示初始化
通过构造方法给成员变量进行初始化
数据初始化完毕,把堆内存的地址值赋值给s变量
static关键字(修饰成员变量,成员方法):针对多个对象有共同的成员变量的时候,Java提供static关键字来修饰
特点:随着类的加载而加载
优先于对象存在
被类的所有对象共享
可以通过类名来调用,也可以通过对象名调用
静态修饰的内容:与类相关的,类成员
注意事项:
A. 静态方法中没有this关键字:静态是随着类的加载而加载,this是随着对象的创建而存在。静态比对象先存在
B. 静态方法只能访问静态的成员变量和静态成员方法。非静态方法可以访问静态或非静态成员变量,也可以访问静态或非静态的成员方法
静态变量和成员变量的区别
所属:静态变量属于类,所有也称为类变量;成员变量属于对象
内存中的位置:静态变量存储于方法区的静态区;成员变量存储于堆内存
内存出现时间不同:静态变量随着类的加载而加载,随着类的消失而消失;成员变量随着对象的创建而存在,随着对象的消失而消失
调用:静态变量可通过类名调用,也可通过对象调用;成员变量只能通过对象名调用
main方法是静态的,不需要创建对象,通过类名就可以,方便JVM调用
继承:多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,多个类无需再定义这些属性和行为,只要继承即可,通过extends关键字实现类与类的继承
好处:提高代码复用性,提高代码维护性,让类与类产生关系,是多态的前提
弊端:耦合性增强了,打破了封装性
特点:Java只支持单继承,不支持多继承,支持多层继承
子类不能继承父类私有方法,只能继承父类所有非私有的成员;子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法;不要为了部分功能而去继承,当子类需要使用父类的所有方法的时候去使用继承,体现“B is a A”的关系。
继承中成员变量的关系:
1)子类中的成员变量和父类中的成员变量不一样。
2) 子类中的成员变量和父类中的成员变量一样。(就近原则)
在子类方法中访问一个变量的查找顺序:
子类方法的局部范围找---->子类的成员范围找----->父类的成员范围找
super关键字:代表父类存储空间的标识(可以理解为父类的引用,可以操作父类的成员)
继承中构造方法的关系:
1)子类中所有的构造方法默认都会访问父类中空参数的构造方法
2)子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。
子类的每一个构造方法的第一条语句默认都是:super()
使用super关键字可以去调用父类的带参构造方法
一个类的初始化过程:成员变量初始化,默认初始化,显示初始化,构造方法初始化
子父类的初始化(分层初始化):先进行父类初始化,然后进行子类初始化
继承中成员方法的关系:
通过子类调用方法:先找子类---->再找父类
方法重写:子类中出现了和父类中方法声明一模一样的方法
注意事项:父类中私有方法不能被重写,因为父类私有方法子类根本就无法继承
子类重写父类方法时,访问权限不能更低。最好一致
方法重写和方法重载的区别:
方法重写override:在子类中出现和父类一样的方法声明的现象
方法重载overload:在同一个类中,出现的方法名相同,参数列表不同的现象
This和super的区别:
this代表当前类的引用
super代表父类的储存空间标识(可以理解为父类的引用,通过super访问父类的成员)
final关键字:可以修饰类,方法,变量
final修饰类,该类不能被继承
final修饰方法,该方法不能被重写。(覆盖,复写)
final修饰变量,该方法不能被重新赋值,此时这个变量就是常量
final关键字修饰局部变量:
final修饰基本类型,值不能变。
final修饰引用变量,是指地址值不变。
fina修饰变量的初始化时机:
被final修饰的变量只能赋值一次
在构造方法完毕前。(非静态的常量)
多态:同一个对象(事物),在不同时刻体现出来的不同状态
前提:要有继承关系或者接口实现关系,要有方法重写,要有父类或者父接口 引用指向子类对象
多态中的成员访问特点:(父类 f = new 子类(); )
1)成员变量:编译看左边,运行看左边。
2)构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化
3)成员方法:编译看左边,运行看右边
4)静态方法:编译看左边,运行看左边(静态和类相关,算不上重写,所以访问还是左边的)
好处:提高代码的维护性(继承保证了这个优点)
提高了代码的扩展性
弊端:不能使用子类的特有功能
对象间转型问题:
向上转型:父类 f = new 子类();
向下转型:子类 z = (子类)f; 要求该父对象必须是能够转换为Zi的
ClassCastException:类型转换异常,可能发生在向下转型中。
抽象类
抽象类的特点:
抽象类和抽象方法必须用abstract修饰
抽象类中比一定有抽象方法,但是有抽象方法的类必须定义为抽象类
抽象类不能实例化
因为它不是具体的。
抽象类有构造方法,但是不能实例化 ?构造方法的作用是什么。用于子类访问父类数据的初始化
抽象类的子类:
a. 如果不想重写抽象方法,该子类是一个抽象类
b. 重写所有的抽象方法,这个时候子类是一个具体的类
抽象方法不能有主体
抽象类的实例化其实是靠具体的子类实现的,是多态的方法
Animal a = new Cat();
抽象类的成员特点:
成员变量:既可以是变量也可以是常量
构造方法:有,用于子类访问父类数据的初始化
成员方法:既可以是抽象的也可以的非抽象的
抽象类的成员方法特性:
A:抽象方法,强制要求子类做的事情
B:非抽象方法,子类继承的事情,提高代码复用性
面试问题: 一个类如果没有抽象方法,可以不可以定义为抽象类,有什么意义:
可以,不让创建对象,不能new实例化
抽象类不能和哪些关键字共存:
private 冲突(非法的修饰符组合);final 冲突;static 无意义。
接口
特点:
接口用关键字Interface表示:interface 接口名{}
类实现接口用implements表示:class 类名 implements 接口名 {}
接口不能实例化:按照多态的方式来实例化
接口的子类:可以是抽象类但是意义不大;可以是具体类,要重写接口中的所有抽象方法。
由此可见多态的体现: 具体类多态,抽象类多态,接口多态
成员特点
成员变量:接口中的变量默认是常量,并且是静态的。默认修饰符:final, static
构造方法:接口没有构造方法。
成员方法:接口方法必须是抽象的。默认修饰符:public abstract
类与类:继承关系,只能单继承,可以多层继承。
类与接口:实现关系,可以单实现,也是可以多实现。并且还可以在继承一个类的同时实现多个接口
接口与接口:继承关系,可以单继承,也可以多继承
抽象类和接口的区别:
成员区别:抽象类:成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:成员变量:只可以常量
成员方法:只可以抽象
关系区别:
类与类:继承,单继承
类与接口:实现,单实现,多实现
接口与接口:继承,单继承 ,多继承
类名作为形式参数:需要该类的对象
抽象类名作为形式参数: 需要该抽象类的子类对象
接口名作为形式参数:需要该接口的实现类对象
类名作为返回值类型:返回该类的对象
抽象类名作为返回值类型:返回该抽象类的子类对象
接口名作为返回值类型:返回该接口的实现类对象
权限修饰符:
本类中 同一个包下(子类和无关类)不同包下(子类) 不同包下(无关类)
private: Y N N N
defualt Y Y N N
protected Y Y Y N
public Y Y Y Y
修饰符:
权限修饰符:private,defualt,protected, public
状态修饰符:static,final
抽象修饰符:abstract
类:权限修饰符:defualt, public;状态修饰符:final;抽象修饰符:abstract
成员变量:权限修饰符:private,defualt,protect, public;状态修饰符:final;抽象修饰符:abstract
构造方法:权限修饰符:private,defualt,protected, public
成员方法:权限修饰符:private,defualt,protect, public;状态修饰符:static,final;抽象修饰符:abstract
比较常见的:public static final int X = 10;
public static void show() {}
public final void show() {}
public abstract void show();
内部类:
定义在其他类中的类。
特点:直接访问外部的成员,包括私有
外部类要访问内部类的成员,必须创建对象。
位置:在成员位置定义的类为成员内部类;直接访问内部类的成员:外部类名.内部类名 对象名 = 外部类对象.内部类对象;成员内部类被static修饰后的访问:外部类名.内部类名 对象名 = new 外部类名.内部类名()
成员内部类的修饰符:private 为了保证数据的安全性;static 为了方便访问数据 静态内部类访问的外部类数据必 须用静态修饰
在局部位置定义的 类为局部内部类;可以直接访问外部类的成员;在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能;
1 /* 2 面试题: 3 要求请填空分别输出30,20,10。 4 5 注意: 6 1:内部类和外部类没有继承关系。 7 2:通过外部类名限定this对象 8 Outer.this 9 */ 10 class Outer { 11 public int num = 10; 12 class Inner { 13 public int num = 20; 14 public void show() { 15 int num = 30; 16 System.out.println(num); 17 System.out.println(this.num); 18 //System.out.println(new Outer().num); 19 System.out.println(Outer.this.num); 20 } 21 } 22 } 23 class InnerClassTest { 24 public static void main(String[] args) { 25 Outer.Inner oi = new Outer().new Inner(); 26 oi.show(); 27 } 28 }
面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么:局部变量是随着方法的调用而调用,随着调用完毕而消失,而推内存的内容并不会消失。所以,加入final修饰。加入final修饰后,这个变量就成了常量。既然是常量,就消失了。
匿名内部类:
内部类的简化写法
前提:存在一个类,抽象类或者是接口
格式:new 类名抽象类名或者接口名(){重写方法;}
本质是什么?该类的子类,抽象类的子类,接口的实现类的匿名对象
1 /* 2 匿名内部类面试题: 3 按照要求,补齐代码 4 interface Inter { void show(); } 5 class Outer { //补齐代码 } 6 class OuterDemo { 7 public static void main(String[] args) { 8 Outer.method().show(); 9 } 10 } 11 要求在控制台输出”HelloWorld” 12 */ 13 interface Inter { 14 void show(); 15 //public abstract 16 } 17 18 class Outer { 19 //补齐代码 20 public static Inter method() { 21 //子类对象 -- 子类匿名对象 22 return new Inter() { 23 public void show() { 24 System.out.println("HelloWorld"); 25 } 26 }; 27 } 28 } 29 30 class OuterDemo { 31 public static void main(String[] args) { 32 Outer.method().show(); 33 /* 34 1:Outer.method()可以看出method()应该是Outer中的一个静态方法。 35 2:Outer.method().show()可以看出method()方法的返回值是一个对象。 36 又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。 37 */ 38 } 39 }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
代码块:
局部代码块:局部位置,用于限定变量的生命周期,及尽早释放提高内存利用率
构造代码块:在类中的方法外出现,把多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行,一般对对象进行初始化
静态代码块:在类中的方法外出现,用static修饰,一般是对类进行初始化。
静态代码块,构造代码块,构造方法的执行顺序?
静态代码块--->构造代码块--->构造方法
且静态代码块只执行一次,构造代码块每次调用构造方法都执行