Java8新特性
1.接口 1)增加default方法和static方法,这两种方法都可以有方法体 interface Interface1 {
static void st1() {System.out.println("static Interface1.st1()");}
default void df1() {System.out.println("default Interface1.df1()");}
}
2)default方法属于实例(对象访问),static方法属于类(接口,只可以通过接口名访问) interface Interface1 {
static void st1() {System.out.println("static Interface1.st1()");}
default void df1() {System.out.println("default Interface1.df1()");}
}
public class Jdk8Test {
public static void main(String[] args) {
//static方法属于类,接口名访问
Interface1.st1();
//报错:default方法不可以通过接口名访问
//Cannot make a static reference to the non-static method df1() from the type Interface1
//Interface1.df1();
Interface1 obj1 = new Interface1() {};
//default方法属于实例,可以通过对象访问
obj1.df1();
//报错:static方法只可以通过接口名访问
//This static method of interface Interface1 can only be accessed as Interface1.st1
//obj1.st1();
}
}
3)接口里面的static方法不会被继承,static变量可以被继承,default方法可以被继承 interface Interface1 {
static void st1() {System.out.println("static Interface1.st1()");}
static String st_str1 = "ststr1";
default void df1() {System.out.println("default Interface1.df1()");}
}
interface Interface2 extends Interface1 {
static void st2() {System.out.println("static Interface2.st2()");}
default void df2() {System.out.println("default Interface2.df2()");}
}
public class Jdk8Test {
public static void main(String[] args) {
//报错,static方法不会被继承
//The method st1() is undefined for the type Interface2
//Interface2.st1();
//static 变量则可以被继承,且可以通过接口名与变量名访问
System.out.println(Interface2.st_str1);
System.out.println(new Interface2() {}.st_str1);;
//default方法可以被继承
new Interface2() {}.df1();
}
}
实例1: interface Interface1 { default void df() {System.out.println("default Interface1.df1()");} } interface Interface2 { default void df() {System.out.println("default Interface2.df2()");} } //报错 //Duplicate default methods named df with the parameters () and () are inherited from the types Interface2 and Interface1 class Class1 implements Interface1,Interface2{} 实例2: interface Interface1 { default void df() {System.out.println("default Interface1.df1()");} } interface Interface2 extends Interface1{ default void df() {System.out.println("default Interface2.df2()");} } //上面加了继承,不再报错子接口的default方法覆盖父接口同名default方法 class Class1 implements Interface1,Interface2{} 实例3: interface Interface1 { default void df() {System.out.println("default Interface1.df1()");} } interface Interface2{ default void df() {System.out.println("default Interface2.df2()");} } //重写接口同名方法,将不会再报错,如果需要访问其中的一个default方法,可以在子类总使用<接口名>.super.方法名的方法指定访问哪一个 class Class1 implements Interface1,Interface2{ public void df() { //指定访问Interface1的default方法 Interface1.super.df(); } public void df2() { //指定访问Interface2的default方法 Interface2.super.df(); } } 实例4:接口的继承亦是如此 interface Interface1 { default void df() {System.out.println("default Interface1.df1()");} } interface Interface2{ default void df() {System.out.println("default Interface2.df2()");} } //重写接口同名方法,将不会再报错,如果需要访问其中的一个default方法,可以在子类总使用<接口名>.super.方法名的方法指定访问哪一个 interface Interface3 extends Interface1,Interface2{ default void df() { //指定访问Interface1的default方法 Interface1.super.df(); } default void df2() { //指定访问Interface2的default方法 Interface2.super.df(); } } //不重写将会报错 //Duplicate default methods named df with the parameters () and () are inherited from the types Interface2 and Interface1 interface Interface4 extends Interface1,Interface2{} 总之:上面的解决方法就是指定访问哪一个重名了的default方法,不过指定有一定的语法要求: ?5)如果一个接口只有一个抽象方法(包括继承的),那么这个接口是一个函数式接口 函数式接口可以使用Lambda表达式实现 如果接口使用了@FunctionalInterface 注解,表明这个接口是一个函数式接口,接口内必须有且只可以有一个抽象方法。 ?6)抽象方法可以在接口中实现(接口继承时在子接口的默认方法中实现,不可以在静态方法中实现)。 2.Lambda表达式 Lambda表达式只可以对函数式接口使用。 2.1?Lambda表达式三部分: () :表示参数列表,不需要指定参数类型,会自动推断 如下代码:
@FunctionalInterface
interface UserTest{
void test();
}
public class TestLambda {
public static void main(String[] args) {
//java8前匿名内部类实现
UserTest ut = new UserTest() {
@Override
public void test() {
System.out.println("匿名内部类实现");
}
};
ut.test();
//java8后使用Lambda表达式实现
//() :表示参数列表,不需要指定参数类型,会自动推断
//-> :表示连接符
//{} :表示方法体
UserTest ut2 = () -> {
System.out.println("使用Lambda表达式实现");
};
ut2.test();
}
}
如果方法体只有一句话,{}可以简化掉,甚至有返回值的时候连return也可省略: @FunctionalInterface
interface UserTest{
void test();
}
@FunctionalInterface
interface UserTest2{
String test();
}
public class TestLambda {
public static void main(String[] args) {
UserTest ut1 = () -> System.out.println("使用Lambda表达式实现UserTest");
ut1.test();
UserTest2 ut2 = () -> "使用Lambda表达式实现UserTest2";
System.out.println(ut2.test());
}
}
如果只有一个参数,()可以省去,两个及以上不可以省略(): @FunctionalInterface
interface UserTest3{
int test(int x);
}
public class TestLambda {
public static void main(String[] args) {
UserTest3 ut3 = x -> ++x;
System.out.println(ut3.test(1));
}
}
输出结果:
2
Lambda表达式访问的外部变量是final的。 Lambda的带来的优点: 可以把java代码作为参数传入,有助于提高代码内聚,Lambda实际上遵循匿名内部类的规则,但不是匿名内部类(Lambda表达式编译后不会生成class文件) ? 2.2 方法的引用 1)引用实例方法: 方法引用时会自动把调用方法的时候的参数,全部全给引用的方法 <函数式接口>? <变量名> = <实例> ::<实例方法名> <变量名>.<函数式接口方法名>([实参]);? 2)引用类方法: 方法引用时会自动把调用方法的时候的参数,全部全给引用的方法 <函数式接口>? <变量名> = <类> ::<类方法名> <变量名>.<函数式接口方法名>([实参]);? 简单示例代码: import java.util.Arrays;
interface MethodRef{
void test(String s);
}
interface MethodRef2{
void test(int[] arr);
}
public class TestFunctionRef {
public static void main(String[] args) {
//Lambda表达式
MethodRef m1 = s -> System.out.println(s);
m1.test("字符串的");
//使用方法引用 :引用实例方法
//这里System.out是一个实例
MethodRef m2 = System.out::println;
m2.test("方法的引用");
//引用类的方法
//这里sort方法是Arrays工具类的静态方法。
MethodRef2 m2_1 = Arrays::sort;
int[] arr = new int[] {3,2,4,7,1,6,5};
m2_1.test(arr);
System.out.println(Arrays.toString(arr));
}
}
3)引用类的实例方法 定义、调用接口方法的时候,需要多传入一个参数,并且参数的类型和引用示例方法的类型必须一致 把第一个参数作为引用的实例,后面的每个参数全部传给引用的方法 interface <函数式接口> { <返回值类型> <方法名> (<类1> <名称>[,其他参数 ...]); } <函数式接口> <变量名> = <类1>::<实例方法名>;? //注意两个类1要是一样的或者兼容的 <变量名> . <方法名>(<类1的实例 [,其他参数]>); 简单代码示例: import java.io.PrintStream;
interface MethodRefX{
void test(PrintStream ps,String s);
}
public class TestFunctionRef2 {
public static void main(String[] args) {
MethodRefX rx = PrintStream::println;
rx.test(System.out,"第二参数");
}
}
上面代码含义为:用类型为PrintStream的实例调用方法名为println的方法,参数为test方法的第二个【及以后】的参数,System.out为PrintStream的一个实例。 4)构造器引用 引用构造器,根据函数式接口的方法名来推断引用哪一个构造器 interface FunctionRefY{
String test(char[] chars);
}
public class TestFunctionRefy {
public static void main(String[] args) {
//引用String类型的public String(char value[])构造器
FunctionRefY fy = String :: new;
String ok = fy.test(new char[] {‘o‘,‘k‘});
System.out.println(ok);
}
}
?3.Stream Stream API是Java 8中加入的一套新的API,主要用于处理集合操作。 Stream(流)是一个来自数据源的元素队列并支持聚合操作 和以前的Collection操作不同, Stream操作还有两个基础的特征: Stream API: 并行流: 2)forEach 3)map 最后输出: 4)filter 最后输出结果: 5)limit 6)sorted 7)skip 8)toArray 转换为数组 9)reduce 10)查询匹配 11)数据收集 规约汇总: 示例代码: package Test_C02; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.alibaba.fastjson.JSON; public class StreamGroup { static class Book{ private String name; private Integer price; private Integer tag; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Integer getTag() { return tag; } public void setTag(Integer tag) { this.tag = tag; } public Book(String name,Integer price,Integer tag) { this.name = name; this.price = price; this.tag = tag; } } public static void main(String[] args) { List<Book> bks = new ArrayList<StreamGroup.Book>(); for(int i = 0;i < 10;i++) bks.add(new Book("nm-"+i,i,i%3)); //计数 Long count = bks.stream().filter(bk -> bk.getPrice()>5).collect(Collectors.counting()); System.out.println("价格大约5的数量:"+count); //最贵的书 Book maxPriceBk = bks.stream().collect(Collectors.maxBy(Comparator.comparing(Book::getPrice))).get(); System.out.println("最贵的书:"+JSON.toJSONString(maxPriceBk)); //最便宜的书 Book minPriceBk = bks.stream().collect(Collectors.minBy(Comparator.comparing(Book::getPrice))).get(); System.out.println("最便宜的书:"+JSON.toJSONString(minPriceBk)); //分组 Map<Integer,List<Book>> group = bks.stream().collect(Collectors.groupingBy(Book::getTag)); System.out.println("以tag进行分组:"+JSON.toJSONString(group)); //多级分组 Map<Integer,Map<String,List<Book>>> group2 = bks.stream().collect(Collectors.groupingBy(Book::getTag,Collectors.groupingBy(bk -> bk.getPrice() > 5 ? "A" : "B"))); System.out.println("多级分组:"+JSON.toJSONString(group2)); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |