枚举、接口、抽象类
object
万类之祖,没有成员变量
native
java中有很多native方法,尤其是自带的类库里面。
native的意思是这个方法没有方法体,它的方法实际代码使用本地来实现的,或者说用c或者c++实现的。它会调用一个编译成仅适合当前操作系统平台的方法
hashCode 与equals
hashCode可以翻译为哈希码,或者散列码。应该是一个表示对象的特征值的int整数
equals是用来判断两个对象上逻辑上是否相等
这两个方法是我们最常覆盖的两个方法。覆盖的原则是equals为true,hashCode就应该相等。 hashCode相等,equals不要求相同
equals与==
反射
Class类
Class类是代表类的类。每个Class类的实例,都代表了一个类
获取当前实例的class对象
> Stu stu = new Stu();
> Class.forName("") //加载一个类,但是这个类是在用到的时候才会初始化。而其他方式的反射获取Class是已经初始化好的
> Class clazz = stu.getClass(); // 获取当前实例的class
> Stu.class; /另一种/获取当前实例的class,类名.class
> clazz.getName();//通过一个类的Class获取当前类的全限定名
> claszz.getZSimpleName();//通过一个类的Class获取当前类的类名
通过反射获取类的成员变量
//通过一个类的Class实例,获取一个类的成员变量
Field countField = claszz.getField("count");
//获取当前参数的类型
countField.getType();
//获取stu实例的count字段的值
countField.get(stu);
//赋值999给stu实例的count字段
countField.set(stu,999);
//获取当前类静态变量的Field对象
Field field = clazz.getField("STATICZ_MEMBER");
//获取这个静态变量的值
field.get(null);
//获取一个类的所有字段的Field对象
clazz.getFields();
通过反射获取类的方法
//通过一个类的Class实例,获取一个类的方法。 int.class是该方法的参数类型
Method buyMethod = clazz.getMethod("buy",int.class);
//执行stu对象的buy方法,参数是1
buyMethod.invoke(stu,1);
通过反射访问类的私有属性和私有方法
//访问私有的属性
Field countField = clazz.getDeclaredField("count");
//如果这个变量是private的时候,需要获取当前Field的值的时候,需要设置accessible参数为true
countField.setAccessible(true);
countField.get(stu);
//访问私有的方法
Method buyMethod = clazz.getMethod("buy",int.class);
buyMethod.setAccessible(true);
buyMethod.invoke(stu,1);
String… 语法糖
//String... args 相当于一个string数组的参数,并且必须放到方法参数的最后一个参数
public static void dyncArgs(int a , String... args){
}
public static void main(String...args){
//调用的时候,不可不传这个参数
dyncArgs(1);
//调用的时候,多个string 可以这么传
dyncArgs(1,"aa","bb","cc")
}
枚举
接口
- 接口的定义使用interface,而非class
- 接口无法被实例化
- 接口中的方法都是public abstract 修饰。方法有名字,参数和返回值。没有方法体。
- 接口中不能定义成员变量。只能定义静态变量,静态变量默认只能并且默认是public static final 。
- 接口甚至可以没有任何方法的定义,只是规定一种类型
- 接口可以多实现
- 一个类实现了一个接口,当前类的引用可以调用这些接口的方法,因为这些方法就在当前类里面。
- 可以用接口的引用,来指向实现了接口的类的实例,然后用接口的引用,来调用接口里面定义的方法。虽然引用是接口的引用,但是执行的还是指向实现接口类实例的方法
- 接口之间可以继承,接口支持多继承。 继承的接口可以有重复的方法,但是签名相同时,返回值必须完全一样(返回值也可以父子关系),否则会编译错误
有方法的接口
在Java8中,接口允许有静态方法、私有方法、缺省实现的抽象方法
缺省的方法用default修饰,可以有方法体
default boolean notExpireInDays(int days){
return false;
}
接口中的静态方法,不需要用default修饰。缺省是public。静态方法可以被实现接口的类继承
public static boolean notExpireInDays(int days){
return false;
}
Java9版本之后的接口,可以后私有方法,不需要用default修饰
private boolean notExpireInDays(int days){
return false;
}
- 有方法的接口,并不是多继承。接口不可以继承类,这一点就打破了
- 同样,接口不可以声明实例变量。其方法是有限制的,因为不能声明实例变量,所以只能通过在来一个获取数据的抽象方法来间接的通过实现接口的类,获取数据
- 和抽象方法不同,如果一个类实现了两个接口,并且两个接口里面有相同的缺省方法,编译器会报错,而抽象方法不会有这种情况,因为抽象类只能被单继承
接口不能创建实例,那它方法里面的this是什么?
缺省的方法,也有this自引用,但是只能调用接口里面的方法,或者继承的接口的方法
因为是new出来的实例,肯定是实现了所有的方法的,this自引用就是指向那个new出来的实例,所以使用起来不会有问题
抽象类
- 抽象类用abstract修饰,抽象类可以继承别的类或者抽象类,也可以实现接口
- 抽象类可以有抽象方法,抽象方法可以来自实现的接口,也可以自己定义
- 抽象类不可以被实例化
- 抽象类可以没有抽象方法,没有抽象方法的抽象类,也不可以被实例化
- 抽象类比起普通类有两点特殊:1> 被abstract修饰,可以有抽象方法 2>不可以被实例化
- 抽象类里面自己定义的抽象方法,可以是protected ,也可以是缺省的,这点跟接口不一样
抽象类比普通类和接口有什么优势
- 比起接口,抽象类可以定义成员变量,和普通方法
- 比起一般的类,抽象类可以强制子类必须实现某个方法(子类是抽象类的话,还是不能被实例化)