Java基础4 接口、lambda表达式和内部类

接口

基本概念

接口不是类,是对类的一组需求描述。这些类要遵从接口描述的统一格式来进行定义
接口不含有实例域,实现实例域和方法实现的任务应该由实现接口的那个类来完成

类对接口的实现(注意接口中的方法和常量的访问属性)

首先要 implements 接口名,其次要在类内对接口的所有方法进行定义(实现)
接口中的方法都默认为public abstract,(因为接口中只定义方法,接口也像祖先类一样充当被派生的祖先,所以每个方法在接口中都是抽象的)
在类中实现这些方法时也必须声明方法为public。如果不声明为public,编译器会认为访问属性为default,即类的默认访问属性(default:只能在 同包 的类中调用。protected:可以在 任意包 的 子类 中调用。public:可在 任意包 中调用。private: 只能在自身类中调用。)

接口中常量默认为public static final:接口不能被实例化,没有构造方法,没有实例变量只有静态变量,故选择static表示变量是属于接口的。如果不是static则表示变量属于对象,只有创建对象才会有这个变量。final为保证所有的变量都是不可变的,必须都在接口中赋初值,只有这样接口内定义的域才不会被实现类改变,这个域才有意义。

Java SE8中可有静态方法,这样不必再给每个接口提供伴随类(用来定义静态方法)了

接口特性

  • 接口不是类,不能使用new实例化接口
  • 可声明接口的变量
  • 接口变量必须引用实现了接口的类对象
  • 可使用instance检查一个对象是否实现了某个接口
  • 接口也可以被拓展public interface Lion extends Animals
  • 接口不可包含实例域或者静态方法,但可以包含常量
  • 接口中的域被自动设为public static final

抽象类和接口的区别

一个类只能extends一个类,但是却可以implements多个接口 。
C++中一个类可extends多个类,称为多重继承,接口提供多重继承大多好处,又可以避免其复杂和低效性。

接口中的方法

静态方法

Java SE8加入了静态方法, 在jdk1.8中,接口可有static方法,但必须有内容且能自己实现,而不需要被实现。
在这里插入图片描述
输出
123
me
print in static method in interface

默认方法

Java SE8中增加了默认方法
default标记的方法,为接口的方法提供了默认实现

  • 在Java API中,被default的方法不必在继承类中实现

  • 接口演化
    为了代码向后兼容,即“源代码兼容”:
    如果之前的接口A被B类实现,A类中想新加方法,又想让原来的B类编译通过,就要将A中新方法设为默认方法。

    默认方法冲突
  • 接口和接口命名冲突
    一个类L同时继承了两个接口A,B,其中有两个相同名称的方法F
    如果至少有一个接口提供了一个默认实现,程序员就必须在类L中提供一个F方法,从A和B的F方法中选择一个

 
 public class Student implements Named,Per{
  	 //覆盖getName方法,而且用public(重写的方法权限要更大)
     //这是必须的否则编译出错
	public String getName() {
		return Per.super.getName();
	}
public static void main(String[] args) {
	Student a=new Student();
	System.out.println(a.getName());//选择Per的方法
}
}
interface Named{
	default String getName() {
		return "yes";
	}
}
interface Per{
	default String getName() {
		return "no";
	}
} 

  • 接口和类冲突
    如果一个类拓展了一个超类,同时实现了一个接口,从超类和接口继承了相同的方法,那么只考虑超类的方法,接口的所有默认方法都被忽略,称为类优先原则

lambda表达式

简述

为何用lambda表达式:
Java的局限,只能用传递对象的方式传递代码块。
lambda的格式:
参数 -> 表达式
如果可从上下文推断出参数的类型,可以忽略不写;参数可有一至多个

public static void Main(string[] args)
        {
            GuangChaoshi gwl = (p, z) =>
            {
                int zuidixiaofei = 10;
                if (p < zuidixiaofei)
                {
                    return 100;
                }
                else
                {
                    return z - p - 10;
                }
           
            };
        	System.out.println(gwl(10,100) + "");   //打印80,z对应参数b,p对应参数a

使用lambda的接口——函数式接口

函数式接口只有一个抽象方法,当需要使用这种接口的对象时,可以提供一个lambda表达式。

Arrays.sort(a[10],(first,second)->first.length()-second.length());
//第二个参数是Comparator实例,接口Comparator只有一个抽象方法
//故该函数式接口的实例可换为lambda表达式

Array.sort方法会接收实现了函数式接口的Comparator类的对象。在这个对象上调用lambda表达式。对象和类的管理全由具体的方法实现。这比内联类高效。
最好将lambda表达式看成一个函数。可以传递这个表达式到专门的函数式接口。

与lambda表达式有关的操作——方法引用

方法引用不会独立存在,总会转换为函数式接口的实例。
3种情况:
对象名::具体方法名
类名::静态方法名
类名::具体方法名
前两种等价于lambda表达式

System.out::println(x)等价于x->System.out::println(x)
//System.out是调用了System类的静态数据对象out
Math::pow等价于(x,y)->Math.pow(w,y)

第三种中,第一个参数将会成为方法的对象,后面的参数成为方法的参数

String::compareToIgnoreCase等价于(x,y)->x.compareToIgnoreCase(y)

方法引用中参数也可以为this,super

类似的,构造器引用

方法名为new

Person::new//Person构造函数的一个引用,选择哪个构造器取决于上下文

特殊的:泛型构造
Java无法构造泛型类型T的数组,因为当new T[n]会变为new Object[n]
(T为类名,如Person)
不可以用Person[] people=stream.toArray(new Person[]);
但可用Person[] people=stream.toArray(Person[]::new);来传入Person引用数组

在lambda表达式中的变量

在lambda表达式中只能引用值不改变的参数(最终变量):
如果在lambda表达式中改变变量值,在并发环境下就会不安全,同样的,如果参数在lambda表达式外改变,也不合法。故引用的变量必须从初始化后就不改变值。
局部变量的同名也不能出现。
在使用this时,指的是lambda表达式的方法的this参数。

public class Application() {
  public void doWork() {
    Runnable runner = () -> {
      ...;
      System.out.println(this.toString());
      ...
    };
  }
}

this.toString()调用的是Application对象的toString(),而不是Runnable对象的

使用lambda表达式

lambda表达式的重点是延迟执行,使用的环境如:
多次运行代码
在算法适当位置运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值