面试准备:Java新特性详解


更多资料,参考 java8 新特性精心整理(全)

Java语言新特性

1.Lambda表达式和函数式接口

比如:

@FunctionalInterface
public interface Comparator<T> {
...
}
# main
Integer[] arr=new Integer[4];
Arrays.sort(arr,(o1,o2)->o2-o1);//Comparator

又比如:

# main
Arrays.asList(1,2,3,4).forEach(System.out::println);//Consumer

不做赘述,参考探索Java8——Lambda表达式

2.接口的默认方法和静态方法

这个之前也介绍过了,也就是jdk8之后接口能够使用default和static方法:

interface Defaulable{
    default String defaultMethod() {
        return "Default implementation";
    }
}
interface DefaulableFactory{
    static Defaulable staticMethod(Supplier<Defaulable> supplier){
        return supplier.get();
    }
}
class Main implements Defaulable{

    public static void main(String[] args) {
        Defaulable defaulable =DefaulableFactory.staticMethod(Main::new);
        System.out.println(defaulable.defaultMethod());
    }
}

当然也可以Override重写:

class Main implements Defaulable{
    @Override
    public String defaultMethod() {
        return null;
    }
    ...
}

3.方法引用

java8方法引用有四种形式:

  • 构造器引用        :   Class :: new
  • 静态方法引用       :   Class :: staticMethodName
  • 类的任意对象的实例方法引用:   Class :: instanceMethodName
  • 特定对象的实例方法引用  :   object :: instanceMethodName

第一种方法引用的类型是构造器引用,语法是Class::new,或者更一般的形式:Class<T>::new。注意:这个构造器没有参数。

class Main {
    public static Main mainFactory(Supplier<Main> supplier){
        return supplier.get();
    }

    public static void main(String[] args) {
        Supplier<Main> supplier=Main::new;
        //等价于  Supplier<Main> supplier=()->new Main();
        Main m=Main.mainFactory(supplier);
    }
}

第二种方法引用的类型是静态或者普通方法引用,语法是Class::staticMethodName

public class Test {
    public static void main(String[] args) {
        //lambda表达式使用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> Test.println(s));
        //静态方法引用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(Test::println);
    }

    public static void println(String s) {
        System.out.println(s);
    }
}

第三种方法引用的类型是某个类的成员方法的引用,语法是Class::instanceMethodName

# main
Arrays.sort(strs, String::compareToIgnoreCase);//Comparator
 
  @FunctionalInterface
  public interface Comparator<T> {
  	  //compare是两个参数,也就是比实际调用的compareToIgnoreCase()多出一个参数。
  	  //第一个参数T o1传的是对象,作用另一个例子会讲到。
      int compare(T o1, T o2);
  }
 
# 而String的compareToIgnoreCase()函数如下:
public int compareToIgnoreCase(String str) {
	//这里实际上使用的是第二个参数T o2
	return CASE_INSENSITIVE_ORDER.compare(this, str);
}

换个例子能更好的理解:

public class Student
{
    
    private String name;
    
    private Integer score;
    
    public void setNameAndScore(String name, Integer score)
    {
        this.name = name;
        this.score = score;
        System.out.println("Student "+  name +"'s score is " + score);
    }
     
    public static void main(String[] args)
    {
        /*lambda表达式的用法:
        TestInterface testInterface = (student, name, score) -> student.setNameAndScore(name, score);*/
        //类的任意对象的实例方法引用的用法:
        TestInterface testInterface = Student::setNameAndScore;
        testInterface.set(new Student(), "DoubleBin", 100);
    }
    
    @FunctionalInterface
    interface TestInterface
    {
        // 注意:入参比Student类的setNameAndScore方法多1个Student对象,除第一个外其它入参类型一致
        public void set(Student d, String name, Integer score);
    }
}

第四种方法引用的类型是某个实例对象的成员方法的引用,语法是object :: instanceMethodName

public class Test
{
    public static void main(String[] args)
    {
        Test test = new Test();
        // lambda表达式使用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> test.println(s));
        // 特定对象的实例方法引用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(test::println);
    }
    
    public void println(String s)
    {
        System.out.println(s);
    }
}

第四种方法其实和第三种差不多,只不多第三个多出了一个参数用来传入了object罢了。

4.重复注解

public class RepeatingAnnotations {
    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    public @interface Filters {
        Filter[] value();
    }

    @Target( ElementType.TYPE )
    @Retention( RetentionPolicy.RUNTIME )
    @Repeatable( Filters.class )
    public @interface Filter {
        String value();
    };

    @Filter( "filter1" )
    @Filter( "filter2" )
    public interface Filterable {
    }

    public static void main(String[] args) {
        for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
            System.out.println( filter.value() );
        }
    }
}
  • @Repeatable( Filters.class )为什么要有后面一段Filters.class
    Filters是保存Filter注解的容器。(可以理解为数组存放了元素)

5.更好的类型推断

Java 8编译器在类型推断方面有很大的提升,在很多场景下编译器可以推导出某个参数的数据类型,从而使得代码更为简洁。例子代码如下:

public class Value< T > {
    public static<T> T defaultValue() {
        return null;
    }

    public T getOrDefault( T value, T defaultValue ) {
        return ( value != null ) ? value : defaultValue;
    }

    public static void main(String[] args) {
        final Value< String > value = new Value<>();
        String s=value.getOrDefault( "22", Value.defaultValue() );
        String s2=value.getOrDefault(null,Value.defaultValue());
    }
}

参数Value.defaultValue()的类型由编译器推导得出,不需要显式指明。在Java 7中这段代码会有编译错误,除非使用Value.<String>defaultValue()

6.拓宽注解的应用场景

之前文章介绍过@Target注解,在JAVA8中,@Target多了这两个类型:

/**
     * Type parameter declaration
     *
     * @since 1.8
     */
     /** 用来标注类型参数 */
    TYPE_PARAMETER,
 
    /**
     * Use of a type
     *
     * @since 1.8
     */
     /** 能标注任何类型名称 */
    TYPE_USE
}
public class TestTypeUse {
 
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TypeUseAnnotation {
         
    }
     
    public static @TypeUseAnnotation class TypeUseClass<@TypeUseAnnotation T> extends @TypeUseAnnotation Object {
        public void foo(@TypeUseAnnotation T t) throws @TypeUseAnnotation Exception {
             
        }
    }
     
    // 如下注解的使用都是合法的
    @SuppressWarnings({ "rawtypes", "unused", "resource" })
    public static void main(String[] args) throws Exception {
        TypeUseClass<@TypeUseAnnotation String> typeUseClass = new @TypeUseAnnotation TypeUseClass<>();
        typeUseClass.foo("");
        List<@TypeUseAnnotation Comparable> list1 = new ArrayList<>();
        List<? extends Comparable> list2 = new ArrayList<@TypeUseAnnotation Comparable>();
        @TypeUseAnnotation String text = (@TypeUseAnnotation String)new Object();
        java.util. @TypeUseAnnotation Scanner console = new java.util.@TypeUseAnnotation Scanner(System.in);
    }
}

Java编译器新特性

参数名称

为了在运行时获得Java程序中方法的参数名称,老一辈的Java程序员必须使用不同方法,例如Paranamer liberary。Java 8终于将这个特性规范化,在语言层面(使用反射API和Parameter.getName()方法)和字节码层面(使用新的javac编译器以及-parameters参数)提供支持。

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
 
public class ParameterNames {
    public static void main(String[] args) throws Exception {
        Method method = ParameterNames.class.getMethod( "main", String[].class );
        for( final Parameter parameter: method.getParameters() ) {
            System.out.println( "Parameter: " + parameter.getName() );
        }
    }
}

JVM的新特性

使用Metaspace(JEP 122)代替持久代(PermGen space)。在JVM参数方面,使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize代替原来的-XX:PermSize和-XX:MaxPermSize。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值