1接口的默认方法-静态方法
1.1 static方法
1.使用static修饰的接口,必须有主体
2.使用static修饰的接口,只能被他本身调用 接口名.方法名
3.使用static修饰的接口,不能被子接口继承
4.使用static修饰的接口,不能被实现类覆写,及直接调用。
1.2 代码
public interface MyInterface {
public abstract void test();
static void staticMethod(){
System.out.println("hello ....");
};
}
public class Test {
public static void main(String[] args) {
MyInterface.staticMethod();
}
}
结论:通过上面的demo,可以测试出,1.1中的1和2点,都符合。
使用static修饰的接口,不能被子接口继承
public interface SubInfarce extends MyInterface{
}
这里显示为红色的波浪线,该子接口没有继承父接口的静态方法。
使用static修饰的接口,不能被实现类覆写,及直接调用
public class MyIntergfaceImpl implements MyInterface {
@Override
public void test() {
}
}
从上面的代码中可以看出,父接口的状态方法,没有重写
2.接口的默认方法-default方法
2.1 demo
public interface MyInterface {
default void defaultMethod(){
System.out.println("hello default ...");
};
}
public class MyInterfaceImpl implements MyInterface {
}
public class Test {
public static void main(String[] args) {
MyInterface myInterface = new MyInterfaceImpl();
myInterface.defaultMethod();
}
}
结论:default方法,不能通过接口的方式调用,一定要有一个接口实现该接口,才能调用。
2.2 demo2
public interface MyInterface {
default void defaultMethod(){
System.out.println("hello default ...");
};
}
public class MyInterfaceImpl implements MyInterface {
@Override
public void defaultMethod() {
MyInterface.super.defaultMethod();
System.out.println("impl");
}
}
public class Test {
public static void main(String[] args) {
MyInterface myInterface = new MyInterfaceImpl();
myInterface.defaultMethod();
}
}
结论:可以在接口中编写逻辑,在实现类中调用。
2.3 demo3
public interface SubInterface extends MyInterface {
}
public class SubInterfaceImpl implements SubInterface {
}
public class Test {
public static void main(String[] args) {
SubInterface sub = new SubInterfaceImpl();
sub.defaultMethod();
}
}
结论:说明接口里面的default方法,能被子接口继承。
3.函数式接口
函数式接口就是有且只有一个抽象方法,但是可以有多个非抽象方法,函数式接口可以隐式的转为lambda表达式。
@FunctionalInterface
public interface MyInterface<functionInterface> {
public abstract void test();
default void defaultMethod(){
System.out.println("hello default ...");
};
}
在接口上增加@FunctionalInterface,注意增加注解以后,就会很严格的判断是不是函数式接口,像如下的demo,因为有两个抽象方法,所以不符合函数式接口。
4.Lambda 表达式
4.1 什么是Lambda表达式
简单的可以看成匿名内部类的简写, 使用Lambda表达式时,接口必须是函数式接口。
4.2 Lambda表达式语法
< 函数式接口> <变量名> = (参数1,参数2....) ->{
// 方法体
}
4.3代码
4.3.1 使用匿名内部类方式
public interface MyInterface {
int sum(int num1,int num2);
}
public class Test {
public static void main(String[] args) {
MyInterface my = new MyInterface() {
@Override
public int sum(int num1, int num2) {
return num1+num2;
}
};
System.out.println(my.sum(123,456));
}
}
4.3.2 使用lambda表达式(接收两个参数)
public class Test {
public static void main(String[] args) {
MyInterface my = new MyInterface() {
@Override
public int sum(int num1, int num2) {
return num1+num2;
}
};
//使用Lambda表达式
MyInterface my1 =(int num1,int num2) -> {
return num1+num2;
};
System.out.println(my1.sum(123,456));
}
}
两种方式,实现的效果一样
Lamda表达式简写
使用Lambda表达式简写:
1.形参参数列表的类型可以不写,会自动推断
2.如果方法中的代码只有一句,可以省略掉{},如果是ruturn返回数据的,可以省略return
MyInterface my2=(num1,num2) -> num1+num2;
4.3.3 使用lambda表达式(接收一个参数,且没有返回值)
public interface MyInterface {
void print(String msg);
}
public class Test {
public static void main(String[] args) {
//使用匿名内部类的方式 打印一句话
MyInterface my = new MyInterface() {
@Override
public void print(String msg) {
System.out.println("Hello "+msg+"...");
}
};
//使用Lambda常规写法
MyInterface my1 = (String msg) -> {
System.out.println("Hello "+msg+"...");
};
//Lambda简写方法
MyInterface my2 = (msg) -> System.out.println("Hello "+msg+"...");
my2.print("Lanbda");
}
}
4.3.4 使用lambda表达式(接收无参数,且没有返回值)
public interface MyInterface {
void test();
}
public class Test {
public static void main(String[] args) {
//匿名内部类
MyInterface my = new MyInterface() {
@Override
public void test() {
System.out.println("666");
}
};
//Lambda表达式
MyInterface my1 = () ->{
System.out.println(666);
};
//简写Lambda
MyInterface my2 =() -> System.out.println(6666);
my2.test();
}
}
4.4 Lambda作用域
在Lambda表达式中访问外层作用域和老版本匿名对象中的方式很相似,可以直接访问标记的final的外层局部变量,或者实例的字段及镜头变量,单如果访问局部变量,要求局部变量必须是final修饰的。
这里的变量a实际上是final类型的,final类型很重要的一点就是不能赋值,实际上,他为了是final,这是因为新版本里面隐式的帮我们做了处理。
4.5 构造方法引用
public interface MyInterface {
Student createStuent(String name,Integer age);
}
public class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
//Lambda常规写法
MyInterface my1 = (name,age) -> new Student(name,age);
//Lambda简写
MyInterface my2 = Student:: new;
Student stuent = my2.createStuent("张三", 14);
System.out.println(stuent.toString());
}
}
4.6 静态方法引用
public interface MyInterface {
int parse(String msg);
}
public class Test {
public static void main(String[] args) {
//常规写法
MyInterface my = msg -> Integer.parseInt(msg);
//简写
MyInterface my1 = Integer::parseInt;
}
}
4.7 实例方法引用
public class Test {
public static void main(String[] args) {
String str = "Hello Lambda";
//使用匿名内部类的方式
Function<String,Boolean> fun = new Function<String, Boolean>() {
@Override
public Boolean apply(String s) {
return str.endsWith(s);
}
};
//使用常规写法
Function<String,Boolean> fun1= s -> str.endsWith(s);
//使用简写
Function<String,Boolean> fun2 = str::endsWith;
Boolean apply = fun2.apply("Lambda");
System.out.println(apply);
}
}
4.8 事例
4.8.1 循环list数组
public class Test1 {
public static void main(String[] args) {
List<String> lists= Arrays.asList("a","b","c","d");
//老版本代码
for (String s:lists){
System.out.println(s);
}
//使用jdk8
lists.forEach(i -> System.out.println(i));
}
}
4.8.2 对数据进行排序
public class Test1 {
public static void main(String[] args) {
// 如果用Lambda表达式,一定要写明泛型
List<String> list = Arrays.asList("peter","anna","make");
/** 老版本代码 */
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
//使用Lambda表达式
Collections.sort(list,(a,b) -> a.compareTo(b));
//简写
Collections.sort(list, String::compareTo);
list.forEach(i-> System.out.println(i));
}
}
4.8.3 stream()
查询学生List中,年龄大于20岁,并输出
List<Student> students = new ArrayList<>();
students.add(new Student("Ted", "Neward", 41));
students.add(new Student("Charlotte", "Neward", 41));
students.add(new Student("Michael", "Neward", 19));
students.add(new Student("Matthew", "Neward", 13));
students.stream().filter((e) -> e.age >20).forEach(System.out::println);
4.8.4 forEach() 使用该方法迭代流中的每个数据
public class Test2 {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Ted", "Neward", 41));
students.add(new Student("Charlotte", "Neward", 41));
students.add(new Student("Michael", "Neward", 19));
students.add(new Student("Matthew", "Neward", 13));
// java 8 前
System.out.println("java 8 前");
for(Student student: students){
System.out.println(student);
}
System.out.println("-------------------------------");
//java lambda
System.out.println("java 8 lambda");
students.forEach(student -> System.out.println(student));
System.out.println("-------------------------------");
//java stream
System.out.println("java stream");
students.stream().forEach( student -> System.out.println(student));
}
}
4.8.5 sorted() 使用该方法排序数据
public class Test2 {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Ted", "Neward", 41));
students.add(new Student("Charlotte", "Neward", 41));
students.add(new Student("Michael", "Neward", 19));
students.add(new Student("Matthew", "Neward", 13));
System.out.println("排序前:");
students.forEach(student -> System.out.println(student));
System.out.println("-----排序后-----");
students.stream().sorted(Comparator.comparing(Student::getAge)).forEach(student -> System.out.println(student));
}
}