java基础

JDK1.7和JDK1.8新特性总结

2018-10-17  本文已影响992人  浅蓝色的麻吉

简单总结一下JDK1.7和1.8的新特性,总体上点到为止,想深入的话还需继续深究其中的原理。

JDK1.7

1. 二进制变量的表示,支持将整数类型用二进制来表示

所有整数int、short、long、byte都可以用二进制表示,表示的方法就是在二进制数字前面加上0b

  byte  num1 = 0b00001001;  //1个字节8位
  short num2 =  0b0010000101000101; //2个字节16位
  int   num3 =  0b10100001010001011010000101000101;; //4个字节32位
  long  num4 = 0b0010000101000101101000010100010110100001010001011010000101000101L;//8个字节64位

        System.out.println(num1);
        System.out.println(num2);
        System.out.println(num3);
        System.out.println(num4);

输出结果:
9
8517
-1589272251
2397499697075167557

2.Switch语句支持String类型。

在1.6的版本switch的参数中只支持byte、short、char、int、long以及他们的包装类(自动拆箱和自动装箱的支持下),然后在jdk1.7支持了String作为参数。

 String str = "1";
      switch (str){
          case "1":
              System.out.println("NO.1");
              break;
          case "2":
              System.out.println("NO.2");
              break;
          case "3":
              System.out.println("NO.3");
              break;
              default:
                  System.out.println("fail");
      }

输出结果:
NO.1

3. Try-with-resource语句

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());
        }
    }
}

在这个例子中,try-with-resources语句包含了两个用分号隔开的声明:ZipFile和BufferedWriter。当代码块中代码终止,不管是正常还是异常,BufferedWriter和ZipFile对象的close方法都会自动按声明的相反顺序调用。


下面的例子用try-with-resources语句自动关闭一个java.sql.Statement对象:

public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";

    try (Statement stmt = con.createStatement()) {
        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");

            System.out.println(coffeeName + ", " + supplierID + ", " +
                              price + ", " + sales + ", " + total);
        }
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    }
}

4.Catch支持多个异常

public static void main(String[] args) throws Exception {
        try {
        testthrows();
        } catch (IOException | SQLException ex) {
        throw ex;
            }
        }
    public static void testthrows() throws IOException, SQLException {
    }

5.数字类型的下划线表示 更友好的表示方式

不过要注意下划线添加的一些标准,下划线不允许出现在开头和结尾。

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; 
    //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 

6.泛型实例的创建可以通过类型推断来简化

可以去掉后面new部分的泛型类型,只用<>就可以了。


新特性之前:

    List strList = new ArrayList(); 
    List<String> strList = new ArrayList<String>(); 
    List<Map<String, List<String>>> strList5 =  new ArrayList<Map<String, List<String>>>();

新特性:

    List<String> strList2 = new ArrayList<>(); 
    List<Map<String, List<String>>> strList3 = new ArrayList<>();
    List<String> list = new ArrayList<>();

7.在可变参数方法中传递非具体化参数,改进编译警告和错误

Heap pollution 指一个变量被指向另外一个不是相同类型的变量。例如

    List l = new ArrayList<Number>();
    List<String> ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown
    Jdk7:
    public static <T> void addToList (List<T> listArg, T... elements) {
    for (T x : elements) {
    listArg.add(x);
    }
    }

你会得到一个warning
warning: [varargs] Possible heap pollution from parameterized vararg type
要消除警告,可以有三种方式
1.加 annotation @SafeVarargs
2.加 annotation @SuppressWarnings({"unchecked", "varargs"})
3.使用编译器参数 –Xlint:varargs;

JDK8的新特性

JDK8新特性

1.接口内允许非抽象方法

Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法。

public interface JDK8Interface {  
  
    // static修饰符定义静态方法  
    static void staticMethod() {  
        System.out.println("接口中的静态方法");  
    }  
  
    // default修饰符定义默认方法  
    default void defaultMethod() {  
        System.out.println("接口中的默认方法");  
    }  
}

2. Lambda 表达式

λ表达式有三部分组成:参数列表,箭头(->),以及一个表达式或语句块。
(x, y) -> { return x + y; } ;

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
 
Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:

Collections.sort(names, (String a, String b) -> {
      return b.compareTo(a);
});

//或者是这样写,可以直接省略掉大括号{}和return关键字。

Collections.sort(names, (a, b) -> b.compareTo(a));

为什么lambda表示式可以这样随意的使用?
lambda表达式是如何和java系统的类型进行对应的?每个lambda表达式都对应一个指定的类型,这个指定的类型是由接口确定的。

功能性接口,它必须且恰好只包含一个抽象方法声明。被指定接口类型所对应的lambda表达式刚好和这个接口的抽象方法想匹配。因为默认方法不是抽象的,因此你可以在你的功能性接口中添加多个默认方法。

我们可以将任意的接口用作lambda表示式,只要该接口仅仅包含一个抽象方法。为了确保你定义的接口达到要求,你可以在接口上添加@FunctionInterface注解。编译器可以检测到该注解并判断你的接口是否满足条件,如果 你定义的接口包含多个抽象方法时,编译器便会报错

例如:下面就是一个功能性接口

@FunctionalInterface
interface Converter<F, T> {
    T convert(F from);
}

进行lambda表示式使用:

Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

3.方法与构造函数引用

Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法.

前部分的示例在使用静态方法引用的情况下可以被进一步的简化:

Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);   // 123

java8可以让你通过关键字::来传递方法和构造函数的引用。上面的示例展示了如何引用一个静态方法。我们同样也可以引用对象方法。

class Something {
    String startsWith(String s) {
        return String.valueOf(s.charAt(0));
    }
}
Something something = new Something();
Converter<String, String> converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted);    // "J"

现在我们将看到关键字::如何为构造函数工作。首先我们定义一个拥有不同构造函数的bean类:

class Person {
    String firstName;
    String lastName;
 
    Person() {}
 
    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

接下来我们定义一个用来创建类person的工厂接口:

interface PersonFactory<P extends Person> {
    P create(String firstName, String lastName);
}

不使用通常的手动实现工厂类,我们通过使用构造函数将所有的工作联合在一起:

PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

JDK8新特性详细使用教程参考

JDK8新特性详细使用教程参考

上一篇下一篇

猜你喜欢

热点阅读