一、Jdk1.8
接口
Default 有方法体
没必要重写
Static
函数式接口 有且只有一个抽象方法的接口
@FunctionInterface
Stream流
1.在接口中的方法
在jdk1.7中default方法和公开静态方法是不会出现的,jdk1.8之后都可以用
//默认值静态常量
public static final int a=10;
//普通的抽象方法
List<String> test1();
//default方法 一定要方法体
default void test2(){
}
//公开静态方法
public static void test3(){
}
//静态方法在Java中不会被继承或重写。
- 函数式接口
函数式接口 有且只有一个抽象方法的接口 @FunctionalInterface
使用@Functionallnterface就只能写一个普通的抽象方法,多写报错!!!
default方法和公开静态方法多个不会报错
3.函数式接口写法
//函数式接口 有且只有一个抽象方法 ()方法参数必须要写
Show show3=() ->{
System.out.println("33333");
return null;
};
show3.test1();
4.函数式接口集合写法
//函数式接口集合 第一种写法
Show show4=()->{
return Arrays.asList("1","2","3");
};
List<String> arrList = show4.test1();
System.out.println(arrList);
//函数式接口简易方法 第二种写法
Show show5=()->Arrays.asList("1","2","3");;
List<String> arrList2 = show4.test1();
System.out.println(arrList2);
- 内实现
//内部类 方法1
Show show=new Show() {
@Override
public List<String> test1() {
System.out.println("22222222");
return null;
}
};
运行后会添加class文件,下面是如何查看文件步骤:
第一步:
第二步:复制该路径去文件中查找 (\out可以不要)
第三步:点击target->classes->com
第四步:查看是否有.class文件 (因为没有取名所以默认为1.class文件)
public class Test {
//内部类 方法2
class Tt{
public String name="张明";
}
}
查看第四步有Test$Tt.class.文件就说明成功了,因为命名为Tt所以XXTt.class文件
- 内实现 非常的常用!!!
//内实现
Show show1=new Showimpl();
- 内部类和内实现的区别
/*内实现/内部类 都是 new这个方法的子类
区别:1.内实现放在其它类只要复制这行照样可以写,多次重复实现
内部类就要复制全部拿过去,多次重复实现就要全部复制
2.内实现只能从实现类里面修改
内部类实现可以直接进行修改*/
- Lambda表达式
1)是匿名函数
2)基本语法: (Parameters) -> expression或 (Parameters) -> {statements: }
3)Lambda表达式由三部分组成:
- Parameters:形参列表,这里的参数是函数式接口里的参数,这里的参数类型可以声明也可不声明。
另外当只有一个推断类型时可以省略圆括号。
- -> :理解为”被用于”的意思
- 方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或什么
都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个或什么都不返回
4)lambda表达式结构 写表达式一定要有return!
1.不需要参数,返回值为 2
()->2
- 接受一个参数(数字类型),返回值
public interface Show1 {
//一个参数 int类型
int test1(int x);
}
//一个参数
Show1 show11=x -> 2*x; //简写
Show1 show12=x->{ //有方法体
return 2*x;
};
System.out.println("int类型 一个参数:"+show11.test1(10));
System.out.println("int类型 一个参数:"+show12.test1(10));
- 接受2个参数(数字类型),并返回其值
public interface Show2 {
//两个参数 int类型
int test2(int x,int y);
}
//两个参数
Show2 show21=(x,y)->{
return x+y;
};
System.out.println("int类型 两个参数:"+show21.test2(2,3));
- 一个参数,无返回值
public interface Show3 {
//一个参数 无返回
void test3(int x);
}
//无返回
Show3 show31 = (x) -> {
System.out.println("无返回 1个参数: " + x);
};
// 调用lambda表达式
show31.test3(10);
- 接受一个String对象, 并在控制台打印,不返回任何值(看起来像是返回void)
(String s)->System.out.print(s)
- 变量捕获
//变量捕获
int a=100;
Show3 show32=(x)->{
System.out.println(a);
};
show32.test3(10);
错误示范: 可以捕获a变量的值进行输出但是不能去修改他的值
//变量捕获
int a=100;
Show3 show32=(x)->{
int a=99; //错误
a=99; //错误
System.out.println(a);
};
show32.test3(10);
- Stream流 (实例)
1.创建一个对象 (要有无参/有参构造方法 get/set方法 toString方法)
public class Student implements Serializable{
private String name;
private int age;
private String className;
private double avg;
private String address;
private String sex;
private String phone;
2.在测试类添加数据
public class StreamTest {
public static void main(String[] args) {
List<Student> studentList=new ArrayList<>();
studentList.add(new Student("小明",18,"一班",98));
studentList.add(new Student("洪明",17,"二班",98));
studentList.add(new Student("小药",18,"三班",98));
studentList.add(new Student("小花",21,"一班",98));
studentList.add(new Student("黄博",26,"二班",98));
studentList.add(new Student("李明",12,"三班",98));
studentList.add(new Student("李明",13,"四班",98));
studentList.add(new Student("李明",14,"二班",98));
//添加多条一样的数据
Student student=new Student("大明",14,"二班",98);
studentList.add(student);
studentList.add(student);
studentList.add(student);
}
}
3.For循环进行”过滤”操作
List<Student> stuList1 = new ArrayList<>();
for (int i=0;i<studentList.size();i++){
Student student2=studentList.get(i);
if(student.getAge()>=20){
stuList1.add(student2);
}
}
System.out.println("For循环 进行 ”过滤” 操作:"+stuList1);
4.Stream流“过滤操作”->stream().filter() 返回boolean类型
//studentList.stream().不能提出来
List<Student> students =
studentList.stream().filter(stu -> { //过滤多个条件
return stu.getAge() >= 20 && stu.getClassName().equals("一班");
}).collect(Collectors.toList());
System.out.println("Stream流 “过滤多个” 操作1:"+students);
List<Student> students2 =
studentList.stream().filter(stu -> stu.getAge() >= 20) // 过滤一个条件
.collect(Collectors.toList());
System.out.println("Stream流 “过滤单个” 操作2:"+students2);
5.”去重“操作 ->stream().distinct()
System.out.println("原长度:"+studentList.size());
List<Student> collect = studentList.stream().distinct().collect(Collectors.toList());
System.out.println("去重后的长度:"+collect.size());
6.”获取前三条数据“操作 ->stream().limit(3) 3可以更改
List<Student> limit = studentList.stream().limit(3).collect(Collectors.toList());
System.out.println("获取前三条数据“操作:"+limit);
7.“排序”操作 ->stream().sorted() 比较对象
//第一种排序方式
List<Student> sorted = studentList.stream().sorted((stu1, stu2) -> {
return stu1.getAge() - stu2.getAge(); //从小到大
}).collect(Collectors.toList());
System.out.println("“排序”操作1:"+sorted);
List<Student> sorted2 = studentList.stream().sorted((stu1, stu2) -> {
return stu2.getAge() - stu1.getAge(); //从大到小
}).collect(Collectors.toList());
System.out.println("“排序”操作2:"+sorted2);
//第二种排序方式
List<Student> sorted3 = studentList.stream().sorted().collect(Collectors.toList());
System.out.println("“排序”操作2:"+sorted3);
第二种排序方式在实体类中
public class Student implements Serializable,Comparable<Student> {
private String name;
private int age;
private String className;
private double avg;
private String address;
private String sex;
private String phone;
@Override
public int compareTo(Student o) {
return o.getAge()-this.getAge();
}
}
8.“任意一条数据”操作 ->stream().anyMatch
“所有数据”操作 ->stream().allMatch
//返回boolean类型
System.out.println("年龄任意一个大于18:"+studentList.stream().anyMatch(stu->stu.getAge()>18));
System.out.println("年龄全部(所有数据)大于20"+studentList.stream().allMatch(stu->stu.getAge()>20));
9.“获取第一条数据”操作 ->stream().findFirst().get()
Student student1 = studentList.stream().findFirst().get();
System.out.println("获取第一条数据:"+student1);
//按照排序方式获取第一条数据
Student student2 = studentList.stream().sorted().findFirst().get();
System.out.println("按照排序方式获取第一条数据:"+student2);
- “从大流里面获取小流 ”操作 -> stream().flatMap
long count = studentList.stream().flatMap(stu -> stu.getScores().stream()).distinct().count(); //去重distinct()及获取总长度count()
System.out.println("“从大流里面获取小流 ”操作:"+count);
在实体类中 (要get/set方法)这是写死了!!
private List<Integer> scores = Arrays.asList(100,98,88,99,45,66,99,78,66,45);
- “对象集合转单属性集合”操作 ->stream().map
List<String> maps = studentList.stream().map(stu -> stu.getName()).collect(Collectors.toList());
System.out.println(" “对象集合转单属性集合 ”操作:"+maps);
- “在重复中获取第一条/最后一条/拼接数据”操作
-> stream().collect(Collectors.toMap())
//对象集合 转成 key 、value
//适合key不重复时使用
//Student::getName ->将getName赋值给Student对象
Map<String, Integer> map = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getAge,
(news, old) -> {
return news ;
}));
map.forEach((k,v) -> {
System.out.println(k + "-" + v);
});
- “跳过”操作 ->stream().skip(2) 2可以修改
List<Student> skip = studentList.stream().skip(2).collect(Collectors.toList());
System.out.println("“跳过” 操作:"+skip);
- “偷偷查看”操作 -> stream().peek
studentList.stream().peek(stu->{
System.out.println("偷偷查看” 操作 "+stu.getSex());
});
接口的作用是什么?
在面向对象编程中,接口是一种抽象类型,它定义了一组方法的签名(方法名称、参数列表和返回类型),但没有提供这些方法的具体实现。接口只定义了方法的契约,而具体的类需要实现这些方法的具体逻辑。接口的作用主要包括以下几点:
实现多态:接口允许不同的类实现相同的接口,从而实现多态。通过接口,可以定义一组共同的方法,不同的类可以根据自身的需求来实现这些方法,实现了代码的灵活性和扩展性。
实现解耦:接口可以帮助实现解耦,即降低类之间的耦合度。当一个类依赖于接口而不是具体的类时,可以更容易地替换实际的实现类,从而降低代码的依赖性。
定义规范:接口定义了一组方法的规范,使得类在实现接口时必须提供这些方法的具体实现。这有助于提高代码的可读性和可维护性,同时也有利于团队协作。
实现多继承:Java 中类只支持单继承,但是一个类可以实现多个接口。通过接口,一个类可以获得多个接口的特性,实现了类的多继承。
实现回调:接口可以用于实现回调机制,即一个对象通过接口调用另一个对象的方法。这种方式可以实现事件处理、监听器等功能。
总的来说,接口在面向对象编程中扮演着重要的角色,它提供了一种抽象机制,使得代码更加灵活、可扩展和易于维护。通过接口,可以定义一组方法的规范,实现多态、解耦和规范化代码的编写。
default的好处是什么?
在Java 8中引入了接口的默认方法(default method),这使得接口可以包含具有默认实现的方法。默认方法在接口中定义,可以被实现接口的所有类继承或覆盖,也可以被类直接调用。默认方法的好处包括:
向后兼容性:引入默认方法后,可以在不破坏现有代码的情况下向接口中添加新的方法。这使得接口的演变变得更加容易,同时保持了现有代码的向后兼容性。
接口的扩展性:默认方法使得接口可以包含方法的默认实现,从而减少了实现类需要实现的方法数量。这样,接口可以在不影响现有实现类的情况下,向接口中添加新的方法。
代码复用:默认方法提供了一种在接口中实现通用逻辑的方式,这样实现类可以直接继承默认方法的实现,避免了重复编写相同的代码。
接口的演化:默认方法使得接口可以逐渐演化,向现有接口中添加新的方法而不需要修改所有实现该接口的类。这有助于在不破坏现有代码的情况下对接口进行修改和扩展。
提供了一种新的设计模式:默认方法的引入为新的设计模式提供了可能性,例如接口的扩展、接口的组合等,使得代码结构更加灵活和易于维护。
总的来说,默认方法为Java接口带来了更大的灵活性和功能性,使得接口可以更好地适应需求的变化,同时提高了代码的复用性和可维护性。