Java 接口

可以将接口方法标记为 public, 将域标记为 public static final

Java 程序设计语言有一个非常重要的内置接口,称为 Cloneable 。如果某个类实现了这个 Cloneable 接口,Object 类中的 clone 方法就可以创建类对象的一个拷贝。

在 Java SE 8 中 ,允许在接口中增加静态方法。理论上讲 ,没有任何理由认为这是不合法的。 只是这有违于将接口作为抽象规范的初衷。
目前为止, 通常的做法都是将静态方法放在伴随类中。在标准库中, 你会看到成对出现的接口和实用工具类, 如 Collection/Collections 或 Path/Paths。

可以为接口方法提供一个默认实现。 必须用 default 修饰符标记这样一个方法。

public interface Comparable<T>{
	default int compareTo(T other) { return 0; }
	// B y default, all elements are the same
}

默认方法可以调用任何其他方法。例如, Collection 接口可以定义一个便利方法:

public interface Collection
{
		int size(); // An abstract method
		default boolean isEmptyO
		{
				return sizeO = 0;
		}

}

回调( callback) 是一种常见的程序设计模式。在这种模式中 , 可以指出某个特定事件发生时应该采取的动作。 例如,可以指出在按下鼠标或选择某个菜单项时应该采取什么行动。
然而,由于至此还没有介绍如何实现用户接口,所以只能讨论一些与上述操作类似 ,但比较简单的情况。

clone 方法是 Object 的一个 protected 方法, 这说明你的代码不能直接调用这个方法。 只有 Employee 类可以克隆 Employee 对象。这个限制是有原因的。想想看 Object 类如何实现 clone。它对于这个对象一无所知, 所以只能逐个域地进行拷贝。 如果对象中的所有数据域都是数值或其他基本类型,拷贝这些域没有任何问题、 但是如果对象包含子对象的引用,拷贝域就会得到相同子对象的另一个引用,这样一来, 原对象和克隆的对象仍然会共享一些信息。

    void learnInterface() throws CloneNotSupportedException {
        Comparable x;
        x = new Employee("tqc", 100);
        class TestClass implements Cloneable {
            Date date;

            public TestClass(Date date) {
                this.date = date;
            }

            @Override
            protected Object clone() throws CloneNotSupportedException {
                return super.clone();
            }
        }
        TestClass testClass1 = new TestClass(new Date());
        TestClass testClass2 = (TestClass) testClass1.clone();
        System.out.println(testClass1.date==testClass2.date);
    }

在这里插入图片描述
1 ) 默认的 clone 方法是否满足要求 ;
2 ) 是否可以在可变的子对象上调用 clone 来修补默认的 clone 方法 ;
3 ) 是否不该使用 clone。

实际上第 3 个选项是默认选项。 如果选择第 1 项或第 2 项,类必须 :
1 ) 实现 Cloneable 接口 ;
2 ) 重新定义 clone 方法,并指定 public 访问修饰符。

深拷贝:

            @Override
            protected TestClass clone() throws CloneNotSupportedException {
                TestClass cloned=(TestClass) super.clone();
                cloned.date = (Date) date.clone();
                return cloned;
            }

lambda表达式

Java 中 已 经 有 很 多 封 装 代 码 块 的 接 口, 如 ActionListener 或 Comparator 。 lambda 表达式与这些接口是兼容的,

    public static <T> void sort(List<T> var0, Comparator<? super T> var1) {

        List<String> words = Arrays.asList(new String[]{"fuck", "cnm", "nimasile"});
        Collections.sort(words,(String a,String b)->a.length()-b.length());
        System.out.println(words);

lambda 表达式可以转换为接口

Jva.util.function 包中有一个尤其有用的接口 Predicate:

public interface Predicate<T>
{
	boolean test(T t);
	// Additional default and static methods
}

ArrayList 类有一个 removelf方法, 它的参数就是一个Predicate。这个接口专门用来传递
lambda 表达式。例如,下面的语句将从一个数组列表删除所有 null 值:

list.removelf(e -> e == null);
    List<Integer> removeIf(List<Integer> list, Predicate<Integer> predicate){
        List<Integer> retList=new ArrayList<>();
        for(Integer i:list){
            if(predicate.test(i)){
                retList.add(i);
            }
        }
        return retList;
    }
        List<Integer> numbers=Arrays.asList(new Integer[]{1,2,3});
        System.out.println(removeIf(numbers,number->number>1));

表达式 System.out::println 是一个方法引用( method reference ), 它等价于 lambda 表达式
x->System.out.println(x)

从这些例子可以看出, 要用: : 操作符分隔方法名与对象或类名。主要有 3 种情况:
•object::instanceMethod
•Class::staticMethod
•Class::instanceMethod
在前 2 种情况中, 方法引用等价于提供方法参数的 lambda 表达式。前面已经提到,System.out::println 等价于 x -> System.out.println(x ) 类似地, Math::pow 等价于(x ,y) ->Math.pow(x, y)对于第 3 种情况, 第 1 个参数会成为方法的目标。例如 ,String::compareToIgnoreCase 等同于 (x, y)-> x.compareToIgnoreCase(y)

在这里插入图片描述在这里插入图片描述
@FunctionalInterface

类似于Python的sort(list,key=…)

Arrays.sort(people, Comparator.comparing(Person::getName)) ;

静态 comparing 方法取一个“ 键提取器” 函数, 它将类型 T 映射为一个可比较的类型( 如 String )。 对要比较的对象应用这个函数, 然后对返回的键完成比较。 例如, 假设有一个Person 对象数组 ,可以如下按名字对这些对象排序:

Arrays.sort(people, Comparator.comparing(Person::getName)) ;

与手动实现一个 Compamtor 相比, 这当然要容易得多。另外, 代码也更为清晰, 因为显然我们都希望按人名来进行比较。
可以把比较器与 thenComparing 方法串起来。例如,

Arrays.sort(people,Comparator.
comparing(Person::getlastName).
thenConiparing(Person::getFirstName)) ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值