1. 程式人生 > >jdk1.7/jdk1.8新特性

jdk1.7/jdk1.8新特性

在面試中經常會問jdk1.6,jdk1.7,jdk1.8的區別:

最近面試的時候的面試官問我jdk8的新特性:
我回答了幾個,他提問到:為什麼defualt沒有被推廣,有什麼弊端。
我很蒙圈,在這裡新增下回答:
我目前還不知道

jdk1.7新增特性:

1.7新特性轉載

1 switch 支援string

jdk1.6: int,short,char,byte,Enum
jdk1.7: string,int,short,char,byte,Enum

2 泛型自動判斷

ArrayList al1 = new ArrayList(); // Old
ArrayList al2 = new ArrayList<>(); // New

3 新的整數字面表達方式 - “0b"字首和”_"連數符

byte b1 = 0b00100001; // New
byte b2 = 0x21; // Old
byte b3 = 33; // Old
System.err.println(b1); //33
這裡有一些其它的不能在數值型字面值上用下劃線的地方:
1 在數字的開始或結尾
2 在浮點型數字的小數點前後
3 F或L下標的前面
4 該數值型字面值是字串型別的時候
int a4 = 5_______2; // 有效的

4.在單個catch程式碼塊中捕獲多個異常,以及用升級版的型別檢查重新丟擲異常

1.6

catch (IOException ex) {
    logger.error(ex);
    throw new MyException(ex.getMessage());
catch (SQLException ex) {
    logger.error(ex);
    throw new MyException(ex.getMessage());
}catch (Exception ex) {
    logger.error(ex);
    throw new MyException(ex.getMessage());
}

1.7

catch (IOException | SQLException | Exception ex) {
    logger.error(ex);
    throw new MyException(ex.getMessage());

可以不用重新指定異常型別

static class FirstException extends Exception { }
static class SecondException extends Exception { }

public void rethrowException(String exceptionName) throws Exception {
    try {
        if (exceptionName.equals("First")) {
            throw new FirstException();
        } else {
            throw new SecondException();
        }
    } catch (Exception e) {
      //下面的賦值沒有啟用重新丟擲異常的型別檢查功能,這是Java 7的新特性
            // e=new ThirdException();
        throw e;
    }
}

5.try-with-resources語句

1.7之前,須在finnally中手動關閉資源

/** 
 * JDK1.7之前我們必須在finally塊中手動關閉資源,否則會導致資源的洩露 
 * @author Liao 
 * 
 */  
public class PreJDK7 {  

    public static String readFirstLingFromFile(String path) throws IOException {  
        BufferedReader br = null;  

        try {  
            br = new BufferedReader(new FileReader(path));  
            return br.readLine();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {//必須在這裡關閉資源  
            if (br != null)  
                br.close();  
        }  
        return null;  
    }  
}

1.7

/** 
 * JDK1.7之後就可以使用try-with-resources,不需要 
 * 我們在finally塊中手動關閉資源 
 * @author Liao 
 */  
public class AboveJDK7 {  

    static String readFirstLineFromFile(String path) throws IOException {  

        try (BufferedReader br = new BufferedReader(new FileReader(path))) {  
            return br.readLine();  
        }  
    }  
}

jdk1.8新增特性:

1.8新特性
1.8主要是簡化寫法

1. default關鍵字

在1.8以前介面內的方法只能是抽象方法,在1.8可以新增default修飾的方法,且實現類不能繼承該方法。
優勢:若需要新增一個統一的方法,以前需要在每一個實現類中繼承,現在只需要在介面類增加一個defualt方法即可。

介面類

public interface interFaceClass {
	void myFuncation();
  default void mydefualtFuncation(){
	  System.err.println("this is a defualt funcation");
  };
}

實現類

public class implementClass implements interFaceClass {
	@Override
	public void myFuncation() {
		// TODO Auto-generated method stub
	}
}

測試類

public static void main(String[] args) {
		interFaceClass test = new implementClass();
		test.mydefualtFuncation();   //this is a defualt funcation
	}

2. 時間類:

localdate
jdk1.8提供了新的API解決之前版本關於獲取時間上繁瑣及SimpleDateFormat的執行緒不安全.總體來看新的API提供了許多便捷的方法獲取想要的時間。
localdate
localtime
localdatetime
zonedatetime
為方便使用和記憶,我在下面的例子中逐一獲取並對比;
測試時間是 2018-09-30
1.7

Date date =  new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd   HH:mm:ss");

//獲取當前時間
date.getDate();// 30
System.out.println(date);//  Sun Sep 30 09:51:04 CST 2018

//按格式獲取當前時間
System.out.println(df.format(date)); // 2018-09-30 09:51:04

//獲取前一天時間
Calendar cal=Calendar.getInstance();
cal.add(Calendar.DATE,  -1);
Date yesterday = cal.getTime();
System.out.println(df.format(yesterday )); // 2018-09-29 09:51:04
		
//獲取指定時間
String dateOfBirthString= "2017-10-11";
Date dateOfBirth = new SimpleDateFormat("yy-MM-dd").parse(dateOfBirthString);
System.out.println(df.format(dateOfBirth )); // 2017/10/11 00:00:00

//比較兩個時間是否相同
boolean flag =  dateOfBirth.equals(dateTody);
System.out.println("flag:  "+flag);// flag;  false

//比價兩個時間的差
//太麻煩了我就不寫了

//將日期轉化為字串
String dateString1 = dateTody.toString;
String dateString2 = df.format(dateTody);

1.8

// 獲取當前時間
LocalDate dateTody = LocalDate.now();
LocalTime timeNow=LocalTime.now();
System.out.println(dateTody+" "+  timeNow);// 2018-09-30  10:36:45.260
int year =  dateToday.getYear();
int month = dateToday.getMonthValue();	
int day =   dateToday.getDayOfMonth();

// 按格式獲取當前時間
DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String text = dateToday.format(formatters);
System.err.println(text);//2018年09月30日

//獲取前一天時間
LocalDate yestoday = dateToday.minusDays(1);
System.err.println(yestoday );//2018-09-29
	
//獲取指定時間
LocalDate dateOfBirth = LocalDate.of(2017, 10, 11);
System.err.println(dateOfBirth );//2017-10-11

//比較兩個時間是否相同
Boolean flag =  dateToday.equals(dateOfBirth);

//比價兩個時間的差
long dy=(   dateToday.toEpochDay() - dateOfBirth.toEpochDay() );
System.err.println("相差:"+dy);//相差:354
	
//將日期轉化為字串
dateToday.toString();


//比較時用的方法:
//一年以後
LocalDate lastYear = dateToday.plus(1,ChronoUnit.YEARS);
System.err.println(lastYear);//2019-09-30

// 取本月第1天:		
LocalDate firstDayOfThisMonth1=dateToday.withDayOfMonth(1);
LocalDate firstDayOfThisMonth = dateToday.with(TemporalAdjusters.firstDayOfMonth()); // 2018-04-01		
// 取本月第2天:		
LocalDate secondDayOfThisMonth = dateToday.withDayOfMonth(2); // 2018-04-02		
// 取本月最後一天,再也不用計算是28,29,30還是31:		
LocalDate lastDayOfThisMonth = dateToday.with(TemporalAdjusters.lastDayOfMonth()); // 2018-04-30		
// 取下一天:		
LocalDate firstDayOfNextMonth = lastDayOfThisMonth.plusDays(1); // 變成了2018-05-01		
// 取2017年1月第一個週一:		
LocalDate firstMondayOf2017 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2017-01-02 

3 lamdba 表示式

“Lambda表示式”是一個匿名函式,是jdk1.8重要的新特性
首先了解下內部類的使用和優點:內部類可以訪問外部類,但只有外圍的外部類才能訪問該內部類,內部類可以使得該類實現多繼承,
匿名內部類是唯一一種沒有構造器的類,且不能有靜態變數
這是一個內部類呼叫
建立靜態內部類物件的一般形式為: 外部類類名.內部類類名 xxx = new 外部類類名.內部類類名()
建立成員內部類物件的一般形式為: 外部類類名.內部類類名 xxx = 外部類物件名.new 內部類類名()

public class outerClass {
	int a=1;	
	class innerClass{
		int a=2;
		void Printable(){
			int a =3;
			System.err.println(a);
			System.err.println(this.a);
			System.err.println(outerClass.this.a);
		}
	}
	
	public static void main(String[] args) {
		outerClass out1 = new outerClass();
		outerClass.innerClass inner2 = out1.new innerClass();
		inner2.Printable();
	}
}
}

匿名內部類

public  abstract  class Person {
	 abstract void f();	
}

Person 是一個抽象類是不能被例項化的,但是我們通過匿名內部類就可以實現對其的向下轉型

public class Test {
	public static void main(String[] args) {
		Person p = new Person() {
			@Override
			void f() {
				// TODO Auto-generated method stub
				System.err.println("我是匿名內部類");
			}
        };
        p.f();
	}
}

上面等效於

Person person=new child();
	person.f(); //child是Person 子類

使用lamdba實現上面的匿名內部類(Person 必須是介面)

 Person p2 =() -> System.err.println("我是匿lambda");
 p2.f();

使用lamdba實現對陣列的遍歷

List<String> list = Arrays.asList("我是1","我是2");
        for ( String a : list) {
			System.err.println(a);
		}      
list.forEach( a -> System.err.println("我是lambda"+a) );// 一句話搞定
list.forEach(System.out :: println);  //println無法寫引數

看了上面的例子我們再來解釋下lambda表示式,由編譯器推斷並幫你轉換包裝為常規的程式碼,因此你可以使用更少的程式碼來實現同樣的功能。
基本語法

(parameters) -> expression
或
(parameters) ->{ statements; }

變數作用域
lambda 表示式只能引用標記了 final 的外層區域性變數,這就是說不能在 lambda 內部修改定義在域外的區域性變數,否則會編譯錯誤。

		String ab="           我是變數";		
		Person p = new Person() {
			@Override
			public void f() {
				// TODO Auto-generated method stub
				System.err.println("我是匿名內部類"+ab);    //匿名內部類一樣會報錯
			}
        };		
        p.f();        
        Person p2 =() -> System.err.println("我是匿lambda"+ab);
        p2.f();
        ab="123131231";  // 當ab變數不賦值時上述方法均不會報錯,但是改變值之後就都報錯了,需要將ab設定為final型別防止出現編譯錯誤

對陣列排序(對下列方法使用lambda改造)

String[] players = {"Rafael Nadal", "Novak Djokovic",   
    "Stanislas Wawrinka", "David Ferrer",  
    "Roger Federer", "Andy Murray",  
    "Tomas Berdych", "Juan Martin Del Potro",  
    "Richard Gasquet", "John Isner"};  
   
// 1.1 使用匿名內部類根據 name 排序 players  
Arrays.sort(players, new Comparator<String>() {  
    @Override  
    public int compare(String s1, String s2) {  
        return (s1.compareTo(s2));  
    }  
});  

lambda

Arrays.sort(players,(s1,s2)->s1.compareTo(s2));//一句話搞定,注意lambda針對的是匿名內部類

4 函式式介面

@FunctionalInterface
java 8提供 @FunctionalInterface作為註解,這個註解是非必須的,只要介面符合函式式介面的標準(即只包含一個方法的介面),虛擬機器會自動判斷, 但 最好在介面上使用註解@FunctionalInterface進行宣告,以免團隊的其他人員錯誤地往介面中新增新的方法。

5 Stream()

自己的總結

  //排序 
String[] players = {"a", "e", "d", "c"};  
        	   
// 1.1 使用匿名內部類根據 name 排序 players  
        	Arrays.sort(players, new Comparator<String>() {  
				@Override
				public int compare(String s1, String s2) {
					// TODO Auto-generated method stub
					  return (s1.compareTo(s2));  
				}  
        	});  
        	
        	for (String string : players) {
				System.err.println(string);
			}
        	
Arrays.sort(players,(s1,s2)->s1.compareTo(s2));

        
//steam()
 List <Integer> steamtest = Arrays.asList(1,2,50,30);

//對元素操作
 List<Integer >   getList =  steamtest.stream().map(a->a*2).collect(Collectors.toList());
		 getList.forEach(System.out::println);

//排序
List<Integer >   getsortList =  steamtest.stream().sorted((a1,a2)->a1.compareTo(a2)).collect(Collectors.toList());
  		getsortList.forEach(System.out::println);	

//過濾      
List<Integer >   getFilterList =steamtest.stream().filter(s-> (s>=2)).collect(Collectors.toList());
      getFilterList.forEach(System.out::println);	

//生成陣列
 Integer[] atest = steamtest.stream().toArray(Integer[]::new); 
     
//對元素疊加計算
 int value = steamtest.stream().reduce(0, (acc,item)->acc+item).intValue();
		 System.err.println(value);

6 HashMap

https://www.cnblogs.com/everSeeker/p/5601861.html