美文网首页
Java SE8结构与新增功能

Java SE8结构与新增功能

作者: 风吹柳_柳随风 | 来源:发表于2019-06-25 13:19 被阅读0次

    Java8简介

            摘自官文文档
            Oracle的Java SE8包含了两个产品:Java SE开发套件(JDK)8和Java SE运行环境(JRE)8。
            JDK8是JRE8的超集,它包含了JRE8中所含有的一切,以及开发applet和应用程序所需的编译器和调试器等工具。JRE8提供了运行用java程序语言编写的applets和程序所需要的类库,java虚拟机(jvm)和其他组件。需要注意的是,JRE包含Java SE规范不需要的组件,包括标准和非标准Java组件。
            以下概念图说明了Oracle Java SE产品的组件:
            Java概念图

    java概念图

    Java7,Java8新增功能

    摘自官方文档

    Java7新增功能

    • Binary Literals——在Java7中,整型(byte, short, int and long)也可以使用二进制数字进行表示。要指定二进制表示,只需在数字添加0b或者0B前缀。示例代码:
    // An 8-bit 'byte' value:
    byte aByte = (byte)0b00100001;
    
    // A 16-bit 'short' value:
    short aShort = (short)0b1010000101000101;
    
    // Some 32-bit 'int' values:
    int anInt1 = 0b10100001010001011010000101000101;
    int anInt2 = 0b101;
    int anInt3 = 0B101; // The B can be upper or lower case.
    
    // A 64-bit 'long' value. Note the "L" suffix:
    long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
    
    • Underscores in Numeric Literals——任意数量的下划线‘_’可以出现在数字文本中的任意位置。这个特性可以让你对数字文本切割分组,这样可以提升代码的可读性。示例代码:
    long creditCardNumber = 1234_5678_9012_3456L;
    long socialSecurityNumber = 999_99_9999L;
    float pi =      3.14_15F;
    long hexBytes = 0xFF_EC_DE_5E;
    long hexWords = 0xCAFE_BABE;
    long maxLong = 0x7fff_ffff_ffff_ffffL;
    byte nybbles = 0b0010_0101;
    long bytes = 0b11010010_01101001_10010100_10010010;
    

    注意!你不能在如下场景下使用:

    1. 不能在文字的开头或结尾使用下划线!
    2. 不能与浮点数中的小数点相邻!
    3. 不能在L或F后缀之前使用!
    4. 不能在预期是一串数字的位置上使用!
      示例代码:
    float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
    float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
    long socialSecurityNumber1
      = 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix
    
    int x1 = _52;              // This is an identifier, not a numeric literal
    int x2 = 5_2;              // OK (decimal literal)
    int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal
    int x4 = 5_______2;        // OK (decimal literal)
    
    int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
    int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
    int x7 = 0x5_2;            // OK (hexadecimal literal)
    int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number
    
    int x9 = 0_52;             // OK (octal literal)
    int x10 = 05_2;            // OK (octal literal)
    int x11 = 052_;            // Invalid; cannot put underscores at the end of a number
    
    public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
         String typeOfDay;
         switch (dayOfWeekArg) {
             case "Monday":
                 typeOfDay = "Start of work week";
                 break;
             case "Tuesday":
             case "Wednesday":
             case "Thursday":
                 typeOfDay = "Midweek";
                 break;
             case "Friday":
                 typeOfDay = "End of work week";
                 break;
             case "Saturday":
             case "Sunday":
                 typeOfDay = "Weekend";
                 break;
             default:
                 throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
         }
         return typeOfDay;
    }
    
    • Type Inference for Generic Instance Creation——你可以使用一组空类型参数(<>)替换调用泛型类的构造函数所需的类型参数,只要编译器可以从上下文中推断出类型参数。示例代码:
    //Java7之前
    Map<String, List<String>> myMap = new HashMap<String, List<String>>();
    //Java7
    Map<String, List<String>> myMap = new HashMap<>();
    
    /*Java SE 7 supports limited type inference for generic instance creation; 
    you can only use type inference if the parameterized type of the constructor is 
    obvious from the context.*/
    List<String> list = new ArrayList<>();
    list.add("A");
      // The following statement should fail since addAll expects
      // Collection<? extends String>
    list.addAll(new ArrayList<>());
    /*Note that the diamond often works in method calls; 
    however, it is suggested that you use the diamond primarily for variable declarations.*/
    // The following statements compile:
    List<? extends String> list2 = new ArrayList<>();
    list.addAll(list2);
    
    • Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods——Java7编译器会在那些有一个non-reifiable类型可变参数的方法或者构造器声明点生成一个警告。Java7采用编译选项-Xlint:varargs和这些注解@SafeVarargs@SuppressWarnings({"unchecked", "varargs"})来压制这个警告。
      原文:The Java SE 7 complier generates a warning at the declaration site of a varargs method or constructor with a non-reifiable varargs formal parameter. Java SE 7 introduces the compiler option -Xlint:varargs and the annotations @SafeVarargs and @SuppressWarnings({"unchecked", "varargs"}) to suppress these warnings.

    non-reifiable类型是指在运行期无法完全获得的类型,例如ArrayList<Number>List<String>等等。
    原文:Most parameterized types, such as ArrayList<Number> and List<String>, are non-reifiable types. A non-reifiable type is a type that is not completely available at runtime.
    示例代码:

    public class ArrayBuilder {
    
      public static <T> void addToList (List<T> listArg, T... elements) {
        for (T x : elements) {
          listArg.add(x);
        }
      }
    
      @SuppressWarnings({"unchecked", "varargs"})
      public static <T> void addToList2 (List<T> listArg, T... elements) {
        for (T x : elements) {
          listArg.add(x);
        }
      }
    
      @SafeVarargs
      public static <T> void addToList3 (List<T> listArg, T... elements) {
        for (T x : elements) {
          listArg.add(x);
        }
      }
    
      // ...
    
    }
    public class HeapPollutionExample {
    
      // ...
    
      public static void main(String[] args) {
    
        // ...
    
        ArrayBuilder.addToList(listOfStringLists, stringListA, stringListB);
        ArrayBuilder.addToList2(listOfStringLists, stringListA, stringListB);
        ArrayBuilder.addToList3(listOfStringLists, stringListA, stringListB);
    
        // ...
    
      }
    }
    
    • The try-with-resources Statement——try-with-resources表达式是一个定义了一个或多个资源的try表达式。一个资源指的是一个在程序结束时必须要调用close方法进行关闭的对象。try-with-resource表达式可以确保每个资源都会在表达式最后进行关闭。任何一个实现了java.lang.AutoCloseable或者java.io.Closeable接口的对象都可以看做一个资源。这些类,java.io.InputStream, OutputStream, Reader, Writer, java.sql.Connection, Statement, ResultSet都可以在try-with-resources表达式中被当做资源进行使用,因为它们都实现了AutoCloseable接口。示例代码:
    //定义一个资源
    static String readFirstLineFromFile(String path) throws IOException {
      try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
      }
    }
    
    //定义多个资源
     public static void writeToFileZipFileContents(String zipFileName, String outputFileName)
        throws java.io.IOException {
    
        java.nio.charset.Charset charset = java.nio.charset.StandardCharsets.US_ASCII;
        java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName);
    
        // Open zip file and create output file with try-with-resources statement
        try (
          java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
          java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
        ) {
    
          // Enumerate each entry
          for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
    
            // Get the entry name and write it to the output file
    
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
          }
        }
      }
    
    //Handling More Than One Type of Exception
    catch (IOException|SQLException ex) {
        logger.log(ex);
        throw ex;
    }
    
    // Rethrowing Exceptions with More Inclusive Type Checking
    public void rethrowException(String exceptionName)
      throws FirstException, SecondException {
        try {
          // ...
        }
        catch (Exception e) {
          throw e;
        }
      }
    

    Java8新增功能

    public class Person {
    
        public enum Sex {
            MALE, FEMALE
        }
    
        String name;
        LocalDate birthday;
        Sex gender;
        String emailAddress;
    
        public int getAge() {
            // ...
        }
        
        public Calendar getBirthday() {
            return birthday;
        }    
    
        public static int compareByAge(Person a, Person b) {
            return a.birthday.compareTo(b.birthday);
     }}
    
    //Reference to a Static Method
    Arrays.sort(rosterAsArray, Person::compareByAge);
    
    //Reference to an Instance Method of a Particular Object
    class ComparisonProvider {
        public int compareByName(Person a, Person b) {
            return a.getName().compareTo(b.getName());
        }
            
        public int compareByAge(Person a, Person b) {
            return a.getBirthday().compareTo(b.getBirthday());
        }
    }
    ComparisonProvider myComparisonProvider = new ComparisonProvider();
    Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
    
    //Reference to a Constructor
    public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
        DEST transferElements(
            SOURCE sourceCollection,
            Supplier<DEST> collectionFactory) {
            
            DEST result = collectionFactory.get();
            for (T t : sourceCollection) {
                result.add(t);
            }
            return result;
    }
    
    Set<Person> rosterSetLambda = transferElements(roster, () -> { return new HashSet<>(); });
    // or
    Set<Person> rosterSet = transferElements(roster, HashSet::new);
    // or
    Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
    
    • Improved Type Inference——Java编译器利用目标类型来推断泛型方法调用的类型参数。表达式的目标类型是Java编译器所期望的数据类型,具体取决于表达式在哪里出现。举个例子,在Java7中,Java编译器通过赋值语句的目标类型来进行推断,而在Java8中,通过上下文中使用的目标类型进行类型推断。示例代码:
    List<String> stringList = new ArrayList<>();
    stringList.add("A");
    
    //在java7中这段会编译出错
    stringList.addAll(Arrays.asList());
    

            你可以在以下的Java教程中获取更多相关的信息:
            1. Target Typing in Lambda Expressions
            2. Type Inference

    • Annotations on Java Types——可以将注释运用在Java类型的任何地方。与可插拔类型系统结合使用,可以对代码进行更强大的类型校验。示例代码:
    //Class instance creation expression
    new @Interned MyObject();
    
    //Type cast
    myString = (@NonNull String) str;
    
    //implements clause
    class UnmodifiableList<T> implements
            @Readonly List<@Readonly T> { ... }
    
    //Thrown exception declaration
    void monitorTemperature() throws
            @Critical TemperatureException { ... }
    

            这种形式的注释称为类型注释。更多信息请查阅 Type Annotations and Pluggable Type Systems

    • Repeating Annotations——在一个定义或类型上允许多次使用同一个注释。查阅更多资料可参考 Repeating Annotations in the new Annotations lesson in the Java Tutorial。示例代码:
    @Schedule(dayOfMonth="last")
    @Schedule(dayOfWeek="Fri", hour="23")
    public void doPeriodicCleanup() { ... }
    
    @Alert(role="Manager")
    @Alert(role="Administrator")
    public class UnauthorizedAccessException extends SecurityException { ... }
    
    • Method Parameter Reflection——你可以通过使用 java.lang.reflect.Executable.getParameters方法来获取任一方法或构造函数形参的名字。(由于 Method类和Constructor类继承了Executable类,所以它们继承了Executable.getParameters方法。)然而.class文件默认是不存储形参的名称。为了实际上能够让.class文件存储形参的名称并且通过Reflection API获取到形参的名称,我们需要在javac编译源文件时加上 -parameters的选项。你可以参考 Obtaining Names of Method Parameters教程。示例代码:
    public class Annotation {
        
        private static final String  fmt = "%24s: %s%n";
        private String name;
        private String method;
        
        public Annotation(String name, String method){
            this.name = name;
            this.method = method;
        }
        
        public static void main(String[] args) {
            Class<? extends Annotation> clazz = Annotation.class;
            Constructor<?>[] constructors = clazz.getConstructors();
            for(Constructor<?> constructor : constructors){
                for(Parameter p : constructor.getParameters()){
                    printParameter(p);
                }
                
            }
        }
        
        public static void printParameter(Parameter p) {
            System.out.format(fmt, "Parameter class", p.getType());
            System.out.format(fmt, "Parameter name", p.getName());
            System.out.format(fmt, "Modifiers", p.getModifiers());
            System.out.format(fmt, "Is implicit?", p.isImplicit());
            System.out.format(fmt, "Is name present?", p.isNamePresent());
            System.out.format(fmt, "Is synthetic?", p.isSynthetic());
        }
    }
    

    输出结果:


    Method Parameter Reflection

    相关文章

      网友评论

          本文标题:Java SE8结构与新增功能

          本文链接:https://www.haomeiwen.com/subject/remeqctx.html