Java8新特性
自己理解的java8的几个新特性。
首先,java8的新特性只有在编译等级为1.8的时候才能编译不报错,如果只是安装了jdk1.8,但是工程编译等级不到1.8,是编译不通过的。
下面就自己理解与测试,描述java8新特性,有增加后续补充。
1.接口的默认方法与静态方法Java8中,接口不再只能包含抽象方法,而可以有已经默认实现的方法和已经实现的静态方法。
默认方法:使用default修饰符修饰,此修饰符并不是方法访问限制修饰符,该方法访问权限依然是public,可以任意访问的,不过其不再抽象,必须在接口中就进行实现。静态方法:Java8中添加了静态方法,静态方法也必须进行实现。而且该接口的静态方法只能通过Interface.method即定义接口类型直接调用方式调用,而不能被实现类对象甚至派生类型调用,即接口的静态方法不可被覆盖和继承。
示例代码如下所示:注释的方法是无法通过编译的,因为并不满足java8的语法限制
1 public interface WithDefaultMethdIntf { 2 3 public void printSth(); 4 5 default void printIntMethod() { 6 System.out.println("this is from the interface"); 7 } 8 9 default void printIntM2() { 10 System.out.println("this is from the interface ,will be override"); 11 } 12 13 /** 14 * default methods in interface must have a body 15 */ 16 //default void printIntM3(); 17 18 19 static void printOfStatic(){ 20 System.out.println("this is static method in interface "); 21 } 22 23 24 /** 25 * static method in interface can not be abstract 26 */ 27 //static void printOfStaticM3(); 28 }
接口的派生类型如下
1 class WithDefaultMethodIntfSon implements WithDefaultMethdIntf { 2 3 @Override 4 public void printSth() { 5 System.out.println("this print from son"); 6 } 7 8 @Override 9 public void printIntM2() { 10 System.out.println("this print from son override intf method 2"); 11 } 12 13 } 14 15 interface WithDefaultMethodIntfSonInft extends WithDefaultMethdIntf{ 16 17 /** 18 * same name static method can defined in son type(class or interface),but is not override 19 */ 20 //@Override 21 static void printOfStatic(){ 22 System.out.println("this is static method in interface "); 23 } 24 25 @Override 26 default void printSth(){ 27 System.out.println("abstract method in interface can be default in son interface"); 28 }; 29 }
下面是调用点的测试:
1 @Test 2 public void testDefualtMethod() { 3 WithDefaultMethdIntf inst = new WithDefaultMethodIntfSon(); 4 // this call the default method in interface 5 inst.printIntMethod(); 6 7 // this call the method in son ,which overrides the interface method 8 inst.printIntM2(); 9 10 // this call the method in son 11 inst.printSth(); 12 13 //This static method of interface WithDefaultMethdIntf can only be accessed as WithDefaultMethdIntf.printOfStatic 14 //inst.printOfStatic(); 15 16 WithDefaultMethdIntf.printOfStatic(); 17 18 }
打印结果为:
this is from the interface
this print from son override intf method 2
this print from son
this is static method in interface
2.函数式接口
函数式接口就是打上@FunctionalInterface后不会报错的接口,该接口只包含一个抽象方法。由于默认方法和静态方法都不是抽象的,因此一个函数式接口可以包含多个默认方法和静态方法。另外,只包含一个抽象方法的抽象类,是不能作为函数式接口的,函数式接口只能是接口类型。
1 @FunctionalInterface 2 public interface WithDefaultMethdIntf { 3 4 public void printSth(); 5 6 default void printIntMethod() { 7 System.out.println("this is from the interface"); 8 } 9 10 default void printIntM2() { 11 System.out.println("this is from the interface ,will be override"); 12 } 13 14 /** 15 * default methods in interface must have a body 16 */ 17 //default void printIntM3(); 18 19 20 static void printOfStatic(){ 21 System.out.println("this is static method in interface "); 22 } 23 24 static void printOfStatic2(){ 25 System.out.println("this is static method2 in interface "); 26 } 27 28 /** 29 * static method in interface can not be abstract 30 */ 31 //static void printOfStaticM3(); 32 } 33 34 35 /** 36 * @author liuming 37 *Invalid '@FunctionalInterface' annotation; FunctionalIntfTest is not a functional interface 38 */ 39 //@FunctionalInterface 40 public interface FunctionalIntfTest { 41 void dosthone(); 42 void dosthTwo(); 43 } 44 45 /** 46 * @author liuming 47 *Invalid '@FunctionalInterface' annotation; LambdaClassTest is not a functional interface 48 */ 49 //@FunctionalInterface 50 public abstract class LambdaClassTest { 51 abstract void classMethodTest(); 52 }
对于函数式接口,甚至可以不在方法参数中定义,直接使用dambda表达式获得函数式接口实例对象。下面的写法都是正确写法
//使用方法引用可以直接生成函数式接口对象 Object inst = new Object(); Supplier<String> stringSupplier = inst::toString; //可以直接使用lambda表达式实例化函数式接口对象 Supplier<String> stringSupplier2 = () -> "test"; Comparable<Object> objectComparable = (a) -> (hashCode() - a.hashCode()); //可以使用强转在引用时如果出现语义冲突,可以使用强转声明表达式的结果类型 System.out.println((Supplier<String>) inst::toString); System.out.println((Supplier<String>) () -> "test");
3.lambda表达式
lambda表达式对我理解来说实际就是函数接口实例化的特有书写形式。
当调用一个方法时,如果其参数为函数式接口,那么就可以使用lambda表达式作为参数传入。
冲突:当一个类有两个同名方法,由两个不同的函数式接口作为参数,且这两个接口的抽象方法相同,编译器会无法判断实例化为哪个接口,这时可以通过强转说明是哪个类型的实例化。
lambda表达式格式:(参数列表)->{实现内容return}
a.参数列表可以可以省略参数类型,省略时可能存在冲突。无参数时,也需要保留括号
b.实现内容如果只有一行,可以省略大括号
1 @Test 2 public void testLambda() { 3 String sa[] = { "c", "b", "a" }; 4 Arrays.sort(sa, (a, b) -> a.compareTo(b)); 5 for (String string : sa) { 6 System.out.print(string); 7 } 8 System.out.println(""); 9 10 Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach(a->System.out.print(a)); 11 System.out.println(""); 12 13 //The method runRunnable(Runnable) is ambiguous for the type Java8Feture 14 //runRunnable(()->System.out.println("parse to Runnable run")); 15 16 runRunnable((Runnable)()->System.out.println("parse to Runnable run")); 17 18 System.out.println("---------test my self inft inst by lambda"); 19 20 runRunnable((MyRunnable)()->System.out.println("parse to MyRunnable run")); 21 22 myLambdaIntf(()->System.out.println("WithDefaultMethdIntf")); 23 24 // The target type of this expression must be a functional interface 25 //functionalClassTest(()->System.out.println("WithDefaultMethdIntf")); 26 27 }
4.方法与构造函数引用
貌似只为lambda表达式服务,类似于lambda表达式简写,而且有参数局限,后续研究
5.stream流式操作
可参考的一篇文章: https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
按照我的理解,stream流的特点有如下几点。
1.获取方式
a.从集合或数组中生成,如:Collection实例对象调用Collection接口的默认方法stream或者parallelStream(并行执行,多核优势),Arrays.stream(T array) or Stream.of()
b.通过Stream.generate(Supplier<T> s)从生产者接口实例获得,此时必须使用limit方法限制大小
c.从一些工具类的方法中获取:
-
- BufferedReader
- java.io.BufferedReader.lines()
- BufferedReader
-
- 静态工厂
-
-
- java.util.stream.IntStream.range()
- java.nio.file.Files.walk()
-
-
- 其它
- Random.ints()
- BitSet.stream()
- Pattern.splitAsStream(java.lang.CharSequence)
- JarFile.stream()
- 其它
2.操作方法分为Intermediate和Terminal模式,即stream的方法
a.Intermediate模式相当于记录要进行的操作,并不立即进行处理,此类方法一般返回类型还是stream
b.Terminal模式方法调用时才开始进行处理,并且消耗stream,此类方法一般返回结果为期望的处理结果
相当于对于一个数据集合,1次stream操作只进行一次集合遍历,每遍历到某个元素都会将所有Intermediate和Terminal操作执行一次,得到最终结果。

浙公网安备 33010602011771号