1.Java8新特性:接口的默认方法实现与静态方法、Lambda表达式、函数式接口、方法与构造函数引用、Optional类、流式处理等重要特性、新的日期与时间API;
2.内部类*:内部类可以对同一个包内的其他类隐藏,可以访问定义这个类的作用域中的数据,包括原本私有的数据
①成员内部类
public class OuterClass{
String str = "成员变量"; //定义一个成员变量
class InnerClass{ //定义成员内部类
//定义一个内部类的成员变量
String str = "内部类的成员变量";
//定义一个内部类的成员方法
public void showInfo(){
//定义内部类的局部变量
String str = "内部类的成员变量";
}
}
}
调用方法:
OuterClass.InnerClass inner = new OuterClass().InnerClass();
//调用内部类的方法
inner.showInfo();
②静态内部类:就是创建成员内部类时在前面加一个static
public class OuterClassS{
static String str = "成员变量"; //定义一个静态变量
static class InnerClass{ //定义静态内部类
//定义一个内部类的成员变量
String str = "内部类的成员变量";
//定义一个内部类的成员方法
public void showInfo(){
//定义内部类的局部变量
String str = "内部类的成员变量";
}
}
}
调用方法:
OuterClassS.InnerClass inner = new OuterClassS.InnerClass();
//调用内部类的方法
inner.showInfo();
③匿名内部类:直接在某个类的内部调用,语法为:接口名 a = new 接口名();
public class OuterClass{
Runnable rable = new Runnable() {
public void run() {
System.out.println();
}
};
}
④局部内部类
3.接口新增方法:使得接口可以声明static和default修饰的方法
①static方法
1.使用static修饰接口中的方法并且必须有方法体(方法主体)。
2.接口中的static方法只能被接口本身调用。
语法:接口名.方法名();
3.接口中的static方法不能被子接口类继承
4.接口中的static方法不能被实现类覆盖(重写)及直接调用
②default方法
1.在接口中被default修饰的方法必须要有方法体
2.接口中的default方法不能直接被自己调用,而是由实现类调用
语法:实现类对象名.方法名();
3.接口中的default方法可以被子接口继承
4.接口中的default方法可以被实现类重写和调用
4.函数式接口:有且只有一个抽象方法,但可以有任意多个default和static方法
@FunctionalInterface //声明当前接口是一个函数式接口
public interface FunctionInterface{
void show();
}
Consumer
Function
Predicate
Supplier
5.lambda表达式:是一个匿名函数,可以把函数作为一个值传递给方法或者存储到变量中
lambda操作符:->
语法:数据类型 对象名 = (参数列表) -> (方法体)
①labmda表达式简写函数式接口:
@FunctionalInterface
interface MyFunction {
int apply(int x, int y);
}
public class Test {
public static void main(String[] args) {
MyFunction add = (x, y) -> x + y;
MyFunction multiply = (x, y) -> x * y;
System.out.println(add.apply(2, 3)); // 输出 5
System.out.println(multiply.apply(2, 3)); // 输出 6
}
}
②集合操作:Lambda表达式可以作为参数传递给集合操作方法,如forEach、map等。
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
names.forEach(name -> System.out.println(name));
names.stream()
.map(name -> name.toUpperCase())
.filter(name -> name.startsWith("A"))
.forEach(name -> System.out.println(name));
}
}
③并行处理:Lambda表达式可以用于实现并行处理,提高程序的性能。
import java.util.stream.IntStream;
public class Test {
public static void main(String[] args) {
IntStream.range(1, 10)
.parallel()
.forEach(i -> System.out.println(i));
}
}
6.方法的引用:是对lambda表达式的优化,当lambda表达式重写的抽象方法,已经有现成的方法可以使用时,此时,lambda表达式就显得冗余了,方法引用的优势是省去了参数的传递。
语法:引用类型 :: 方法名
①静态方法的引用:使用类名来调用静态方法
类名 :: 方法名
public class Test {
public static void print(String s) {
System.out.println(s);
}
public static void main(String[] args) {
Consumer<String> consumer = Test::print;
consumer.accept("Hello, world!");
}
}
②实例方法的引用:使用对象实例来调用实例方法
类名 :: 方法名
③对象方法的引用:使用对象名来调用对象方法
对象名 :: 方法名
④构造方法的引用:使用类名来调用构造方法
类名 :: new
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class Test {
public static void main(String[] args) {
Supplier<Person> supplier = Person::new;
Person person = supplier.get();
person.setName("Alice");
person.setAge(20);
System.out.println(person.getName() + ", " + person.getAge());
}
}
静态方法与实例方法的区别:
1.静态方法引用是使用类名调用方法,而实例方法引用是使用实例对象调用方法。
2.静态方法引用可以使用任意符合函数式接口的方法作为目标方法,而实例方法引用只能使用符合该函数式接口的实例方法作为目标方法。
3.静态方法引用不依赖于实例对象,而实例方法引用依赖于实例对象
7.stream流处理:是一种集合(Collection)和数组(Array)操作的新方式
Stream API提供了一种流式处理数据的方式,可以对数据集合进行筛选、映射、排序、聚合等各种操作,提供了并行处理的支持,可以将数据集合分成多个子集,使用多个线程来并行处理,从而提高了处理数据集合的效率。
获取Stream:通过Arrays.asList()、通过Stream提供的方法Stream.of(T...value)、Arrays.stream()
- filter:用于过滤流中的元素;
- map:用于将流中的元素进行映射;
- flatMap:用于将流中的元素扁平化;
- sorted:用于对流中的元素进行排序;
- distinct:用于去除流中的重复元素;
- limit:用于限制流中元素的数量;
- skip:用于跳过流中的元素;
- forEach:用于遍历流中的元素;
- collect:用于将流中的元素收集到一个集合中;
- reduce:用于对流中的元素进行归约操作。
- count:返回流中元素个数
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.forEach(System.out::println);
}
}