1. 封装
封装的最基本单位是对象,封装的最基本目标是“高内聚、低耦合”。对于用户来说,对象是如何对各种行为进行实现是不需要刨根问底了解清楚的,大大地简化了操作的步骤,使用户使用起来更加高效、更加得心应手。
一般可以将需要封装的数据私有化private,然后给用户提供get/set方法来获取数据。
2. 继承
Java是单继承
继承好处:提高了代码的复用性、维护性
继承弊端:类的耦合性增强了
继承体现的关系:is a
设计时可以抽象子类的共有特征来构成父类
this:代表本类当前对象的引用
super:代表父类对象的引用
继承中变量的访问顺序:
子类局部范围找
子类成员范围找
父类成员范围找
如果都没有就报错(不考虑父类的父类)
继承中成员方法的访问顺序:
子类成员范围找
父类成员范围找
如果都没有就报错(不考虑父类的父类)
继承中构造方法的访问特点:
子类中所有构造方法第一条语句默认都是:super(),因为子类会继承父类中的数据,可能还会使用父类中的数据,因此子类初始化之前,一定要先完成父类数据的初始化。
若父类中没有无参构造,只有带参构造,需要显示使用super去调用父类带参构造方法,因此创建类时最好都写上无参构造。
方法重写时子类方法访问权限不能比父类的低
一个类如果没有父类,默认继承自Object类
运行时,父类先进方法区;父类中的属性,会跟随子类对象进入到堆内存
3. 多态
多态简单理解:同一个对象在不同时刻表现出不同形态
多态的前提和体现:
有继承/实现关系
有方法重写
有父(类/接口)引用指向(子/实现)类对象
多态好处:提高了程序的扩展性;如在定义方法时,使用父类作为参数,将来使用时用具体子类参与操作
多态弊端:不能使用子类特有功能
多态中成员的访问特点:只有运行时的非静态方法看右边
编译时:变量和方法都看左边。因为编译时右边new的对象还没有被调入到堆内存。
运行时:变量看左边,静态方法看左边,非静态方法看右边。因为左边的声明类型可能是接口,方法是抽象的,所以运行时方法要看右边的。
向上转型:子类转换为父类,父类引用指向子类对象,安全
向下转型:父类转换为子类,父类引用转为子类引用,不安全
instanceof运算符:判断一个对象是否为一个类的实例
4. 抽象
抽象类主要对类进行抽象
使用abstract修饰抽象类和抽象方法
一个没有方法体的方法应该定义为抽象方法
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类
抽象类不能实例化,但有构造方法,用于子类访问父类数据的初始化
abstract和final不能同时使用,因为abstract是让子类重写,而final是不可重写
abstract和private不能同时使用,因为abstract是让子类重写,private要求只能本类使用,子类根本继承不了
abstract和static不能同时使用,因为abstract是让子类重写,static修饰的方法不能被重写
5. 接口
接口主要对行为进行抽象
一个类/接口可以同时实现/继承多个接口
接口不能直接实例化,可以通过实现类对象实例化
接口的实现类要么重写接口中的所有抽象方法,要么是抽象类
接口没有构造方法
接口中的成员变量只能是常量,默认修饰符为public static final
接口中的方法只能是抽象方法,默认修饰符为public abstract
接口的组成:
常量
抽象方法
默认方法(Java 8)
静态方法(Java 8)
私有方法(Java 9)
接口中默认方法不是抽象方法,所以不强制被重写,但可以被重写,重写的时候去掉default关键字
接口中默认方法的定义格式:
public default 返回值类型 方法名(参数列表) {}
定义时public可以省略,default不能省略
接口中静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
接口中静态方法的定义格式:
public static 返回值类型 方法名(参数列表) {}
定义时public可以省略,static不能省略
接口中私有方法:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性
接口中私有方法的定义格式:
格式1:private 返回值类型 方法名(参数列表) {}
格式2:private static 返回值类型 方法名(参数列表) {}
默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法
6. 内部类
内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
外界创建非私有的成员内部类:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
如:Outer.Inner oi = new Outer().new Inner();
局部内部类是在方法中定义的类,外界无法直接使用,需要在方法内部创建对象并使用。
匿名内部类:本质是一个继承了该类或者实现了该接口的子类匿名对象
格式:
new 类名或接口名() {
重写方法;
}
7. 成员变量和局部变量的区别
成员变量
局部变量
在类中,方法外
在方法内或方法声明上
堆内存
栈内存
随对象的存在而存在
随方法的调用而存在
有默认值
无默认值
8. 访问权限
权限
同类
同包
不同包子类
不同包非子类
public
√
√
√
√
protected
√
√
√
default(不写)
√
√
private
√
外部类只能用public或default(不写)这两种修饰符;内部类四种都可以用
protected权限用法:只能在子类中使用super才能访问父类
private修饰的方法不能被重写,因为private修饰的成员只能在本类中访问
9. static
被static修饰的内容在静态区中,随着类的加载而加载;不属于对象,而是属于类的;凡是本类的对象,都共享同一份。
class Student {
private int id;
private static int idCounter = 0; // idCounter:学号计数器
public Student() {
// 每当new一个新对象时,自动给id赋值
id = ++idCounter;
}
}
静态代码块:
特点:当第一次用到本类时,静态代码块执行唯一的一次**(无论创建多少对象,只在第一次的时候执行)**
典型用途:用来一次性地对静态成员变量进行赋值
静态内容总是优先于非静态,所以静态代码块比构造方法先执行
static {
// 静态代码块的内容
}
通过类名访问静态成员变量时,全程和对象就没关系,只和类有关系
无论成员变量还是成员方法,如果被static修饰了,都推荐使用类名进行调用
静态不能直接访问非静态,因为在内存中先有静态,后有非静态。–>前人不知道后人,但后人知道前人
static不可以修饰局部变量,因为静态成员属于类,不属于方法
静态方法不能使用this,因为this代表当前对象,通过谁调用的方法,谁就是对象,但是静态却与对象没关系
静态方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名参数列表相同静态方法,那么该子类的方法会把原来然承过来的父类的方法隐藏,而不是重写。
静态内部类可以定义静态和非静态的方法和属性,而非静态内部类只能定义非静态方法和属性。因为非静态内部类在创建对象时才出现,若内部有静态成员,则该静态成员需在创建对象前就出现,相互矛盾。
静态属于类,不属于对象,因此静态不能对象序列化
10. final
被final修饰的类不能被继承;一个类如果是final的,那么其中所有成员方法都无法被覆盖重写(因为没儿子)
// 格式
权限修饰符 final class 类名称 {
}
被final修饰的方法不能被覆盖重写
// 格式
权限修饰符 final 返回值类型 方法名(参数列表) {
}
被final修饰的局部变量不可改变,一次赋值,终生不变。对于基本类型来说,不可变指变量中的数据不可改变;对于引用类型来说,不可变指变量的地址不可改变
// 格式 只保证有唯一一次赋值即可
final 数据类型 变量名;
被final修饰的成员变量同样不可变且没有默认值
被final修饰的成员变量,要么直接赋值,要么通过构造方法赋值,二者选其一。
如果选择使用构造方法赋值,那么必须保证类中所有重载的构造方法,都对被final修饰的成员变量赋值。
被final修饰的成员变量,不能有set方法。
若有错误或补充,欢迎私信