java核心技术10阅读(四)-接口、lambda表达式和内部类

接口概念

接口的为对象提供更多的功能。接口中的所有方法自动地属于public。因此, 在接口中声明方法时, 不必提供关键字。且接口中不能含有实例域。
类中必须实现相应的接口方法,且声明public,类中方法默认为包可见。
例如想要调用sort功能的对象,需要具有comparable接口,而类中需要具体实现comparable接口方法。调用sort:Aarry.sort(Object)

需要接口的主要原因在于Java 程序设计语言是一种强类型( strongly typed) 语言。在调用方法的时候, 编译器将会检查这个方法是否存在。而 接口就确保了这种类型变量的方法存在。

接口中不符合**“ 反对称” 的规则**。如果x 是一个Employee 对象,y 是一个Manager 对象,
调用x.compareTo(y) 不会抛出异常, 它只是将x 和y 都作为雇员进行比较。但是反过来,
y.compareTo(x) 将会抛出一个ClassCastException。解决方法如下:
(1)子类之间的比较含义不一样, 那就属于不同类对象的非法比较。每个compareTo 方法都应该在开始时进行下列检测:if (getClassO != other.getClassO) throw new ClassCastExceptionO;
(2)若比较含义一样,如果存在这样一种通用算法, 它能够对两个不同的子类对象进行比较, 则应该在超类中提供一个compareTo 方法, 并将这个方法声明为final ,

接口特性

接口,且能定义接口变量,引用实现了接口类的对象。可以利用 instanceof 检测对象的接口类型
接口可以拓展继承,和类一样使用extends.。其次,接口中的域被自动设置为public static final,即常量。

允许在接口中增加静态方法, 但这和接口的拓展初衷不一样。

以为接口方法提供一个默认实现。必须用default 修饰符标记这样一个方法。默认方法将会被覆盖,不过有些情况下比较有用,可以让使用者不用担心某些方法。默认方法中可以调用接口其他方法

到很多接口都有相应的伴随类,这个伴随类中实现了相应接口的部分或所有方法, 如CoUection/AbstractCollectkm 或MouseListener/MouseAdapter。在JavaSE 8 中, 这个技术已经过时。现在可以直接在接口中实现方法。=》为接口实现默认方法可以保证源码兼容

解决默认方法冲突:(1)超类优先(2)覆盖解决接口冲突,如果至少有一个接口提供了一个实现, 编译器就会报告错误, 而程序员就必须解决这个二义性

java利用对象来实现回调,要求传递的对象所属的类实现了回调对象所属的接口。
ArrayS.Sort 方法还有第二个版本, 有一个数组和一个比较器( comparator ),来实现自定义的比较,comparator利用对象来传入sort方法中。将这个调用与words[i].compareTo(words[j]) 做比较。这个compare 方法要在比较器对象
上调用, 而不是在字符串本身上调用

对象克隆

为什么对象不能访问从Object继承过来的受保护的clone方法?
// Java 包的作用域会影响 protected 和 default 的访问限制。在不同的包中 protected 恢复原有的特性,而 default 则被提升为 private。
对于protected的成员或方法,要分子类和超类是否在同一个包中。与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员(例如anObeject.clone))。在相同包时,protected和public是一样的。实际上对象是可以调用Clone方法,其次lone方法的调用有着特殊的规定

/**
     * @return     a clone of this instance.
     * @throws  CloneNotSupportedException  if the object's class does not
     *               support the {@code Cloneable} interface. Subclasses
     *               that override the {@code clone} method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    @HotSpotIntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;

Object.clone()方法是一个native方法,简单地讲,一个native方法就是一个java调用非java代码的接口。而一般native方法的速度都要比你自己所写的程序运行速度快很多,这也是为什么当我们想要对一个对象进行克隆操作时,推荐使用Object.clone()方法而非自己通过java代码去实现这样一个功能(虽然也可以达到想要的结果)。
@throws后面的内容说明了如果一个类没有实现Cloneable接口,或者一个子类试图重写clone方法都会抛出CloneNotSupportedException这个异常
原文链接:https://blog.csdn.net/qq_41409138/article/details/86762163

Cloneable 接口是Java 提供的一组标记接口,标记接口不包含任何方法; 它唯一的作用就是允许在类型查询中使用instanceof。
对象对于克隆很“ 偏执”, 如果一个对象请求克隆, 但没有实现这个接口, 就
会生成一个受査异常。

lambada表达式

函数式编程能够直接处理代码块,例如传入鼠标事件处理含函数。
lambda 表达式就是一个延迟执行的代码块, 以及必须传人 代码的变量规范
lambada表达式相当于接口对象中方法的简写,而不用去定义接口对象。换而言之,lambda 表达式与这些接口是兼容的
对于只有一个抽象方法的接口, 需要这种接口的对象时, 就可以提供一个lambda 表达
式。这种接口称为函数式接口

例如Comparator 就是只有一个方法的接口,comparator接口的写法可以:
Arrays.sort (planets, (first , second) -> first .lengt() - second .length()) ; //planets为字符串,所以推测first和second变量也为字符串对象

Timer t = new Timer(1000, Systei.out::println) ;
表达式System.out::println 是一个方法引用( method reference ), 它等价于lambda 表达式x 一> System.out.println(x)

构造器引用与方法引用很类似,只不过方法名为new。例如,Person::new 是Person 构造器的一个引用。哪一个构造器呢? 这取决于上下文。
Java 有一个限制,无法构造泛型类型T 的数组, 表达式new T[n] 会产生错误,因为这会改为new Object[n]

lambda 表达式有3个部分:
1 ) 一个代码块;
2 ) 参数;
3 ) 自由变量的值, 这是指非参数而且不在代码中定义的变量。关于代码块以及自由变量值有一个术语: 闭包(closure)。lambda就是闭包。在lambda 表达式中, 只能引用值不会改变的变量。

lambda 表达式中捕获的变量必须实际上是最终变量( effectivelyfinal)。
lambda 表达式的体与嵌套块有相同的作用域。

lambda 表达式的重点是延迟执行(deferred execution )。

Comparator 接口包含很多方便的静态方法来创建比较器。例如:
Arrays.sort(people,Comparator.comparing(Person::getlastName).thenConiparing(Pe rson::getFirstName)) ;

发布了15 篇原创文章 · 获赞 1 · 访问量 133

猜你喜欢

转载自blog.csdn.net/qq_17236715/article/details/103842197