接口
1.接口描述类应该做什么,而不是指定具体如何去做,一个类可以实现多个接口。接口中 所有方法都是public,因此不必提供关键字,但是实现接口时要提供。
2.接口不能有实例字段,但是可以有常量,总是public static final
3.让类实现一个接口:将类声明为实现给定的接口 implements, 对接口中的所有方法提供定义。
4.调用sort函数需要数组元素实现了Comparable接口。
5.不能实例化一个接口,但是可以声明接口变量Comparable x = new Employee(),接口变量引用实现了这个接口的类对象。可以使用instanceof检查一个对象是否实现了某个特定接口。
6.记录和枚举可以实现接口,接口可以密封,必须在permits中声明。
7.静态方法一般在伴随类中,可以为接口方法提供一个默认实现,用default修饰。
8.默认方法冲突: 超类优先,接口冲突则覆盖,接口和类冲突则继承类方法,所以不能创建一个默认方法覆盖Object类中的某个方法。
9.Cloneable接口是标记接口,不包含任何方法,唯一作用是允许在类型检查查询时使用instanceof
,即使clone的默认实现能够满足要求,还是要实现Cloneable接口,将clone重新定义为public,在调用super.clone()。
lambda表达式
1.lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。(String first, String second) -> first.length() - second.length()
2.引用timer,一般是javax.swing里面的
3.对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。称为函数接口。lambda所能做的也只是转换为函数式接口。可以用@FunctionalInterface
4.方法引用 System.out::println 指示编译器生成一个函数式接口的实例,为一个类型为函数式接口的变量赋值时会生成一个对象。要用::分隔方法名与对象或类名。只有当lambda表达式只调用一个方法而不做其他操作时,才能把lambda表达式重写为方法引用。可在方法引用中使用this参数,super同理。
5.构造器引用 Person::new 通过上下文推导出调用哪一个构造器,可以用数组类型建立构造器引用 如 int[]::new,参数 数组长度。 无法构造泛型类型T的数组。可以Person[] people = stream.toArray(Person[]::new)
6.变量作用域,lambda表达式就是闭包 ,lambda表达式可以捕获外围作用域中变量的值,只能引用值不会改变的变量。lambda表达式捕获的变量必须是事实最终变量,即初始化之后不会再为它重新赋值。lambda表达式的体与嵌套块有相同的作用域。在lambda表达式中声明一个局部变量同名的参数或局部变量是不合法的。在一个lambda表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数。
7.处理lambda表达式,延迟执行。
8.Comparator接口包含很多方便的静态方法来创建比较器,这些方法可用于lambda 表达式或方法引用,静态comparing 接受一个”键提取器“ 将类型T映射为一个可比较的类型,然后对返回的键完成比较Arrays.sort(people, Comparator.comparing(Person::getName)).
内部类
1.定义在另一个类中的类:内部类可以对一个包中的其他类隐藏 内部类方法可以访问定义这些方法的作用域中的数据,包括原本私有的数据据。内部类的对象有一个隐式引用,指向实例化这个对象的外部类对象,通过这个指针,它可以访问外部对象的全部状态。静态内部类没有这个指针。
2.使用内部类访问对象状态,外部类的引用在构造器中设置,编译器会修改所有内部类的构造器,添加一个对应外部类引用的参数。内部类的好处,不需要提供只有另一个类感兴趣的访问器。可以把内部类设为私有,只有内部类可以是私有的。
3.内部类的特殊语法规则,外部类引用的正规语法OuterClass.this,外部类的作用域之外引用内部类OuterClass.InnerClass。内部类中所有静态字段都必须是final ,并初始化为一个编译时常量。内部类不能有static方法。
4.内部类转换为常规的类文件,用$分隔外部类名与内部类名,如TalkingClock$TimePrinter。
5.局部内部类,声明局部类时不能有访问说明符(public等),局部类的作用域总是限定在声明这个局部类的块中,对外部世界完全隐藏,甚至外部类中的其他代码也不能访问它。
6.外部方法访问变量,与其他内部类相比,局部类可访问局部变量(事实最终变量)
7.匿名内部类 只想创建这个类的一个对象,甚至不需要为类指定名字
new SuperType(constrution parameters){
inner class methods and data
}
SuoerType可以是接口,内部类要实现这个接口,也可以是类,内部类要扩展这个类。匿名内部类没有构造器,只要内部类实现一个接口,就不能有任何构造参数。如果构造参数列表的结束小括号后面跟一个开始大括号,就是在定义匿名内部类。尽管匿名类不能有构造器,但是可以提供一个对象初始化块。
var bob = new Object(){ String name = "bob";}
System.out.println(bob.name);
使用var定义,变量会了解增加的字段或方法,但是如果声明bob的类型为Object,bob.name将无法编译。
8.静态内部类 有时候使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类有外部类对象的一个引用,可以把内部类声明为static。只有内部类可以声明为static ,静态内部类的对象没有其他外部类对象的引用。只要内部类不需要访问外部类对象,就应该使用静态内部类。与常规内部类不同,静态内部类可以有静态字段和方法。在接口中声明的内部类自动是static public。类中声明的接口、记录和枚举都自动为static。
服务器加载
1.利用ServiceLoader类可以很容易地加载符合一个公共接口的服务。
代理
1.使用代理可以在运行时创建实现了一组给定接口的新类,只有在编译时无法确定需要实现哪个接口时才有必要使用代理。代理类可以在运行时创建全新的类,代理类能够实现你指定的接口。
代理类包含以下方法:指定接口所需要的全部方法,Object类中定义的全部方法。不过不能在运行时为这些方法定义新的代码,必须提供一个调用处理器,实现了InvoationHandler接口的类的对象。这个接口只有一个方法 Invoke()。
2.创建代理对象,使用Proxy类的newProxyInstance方法。
3.代理类是再程序运行过程中创建的,一旦创建就是常规的类,所有的代理都扩展proxy类,一个代理只有一个实例字段-调用处理器。
4.代理类总是public final。