這篇文章將為大家詳細(xì)講解有關(guān)Java5、Java6、Java7、Java8的新特性是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
因?yàn)榕驼嬲\(chéng),有更多的客戶和我們聚集在一起,為了共同目標(biāo),創(chuàng)新互聯(lián)在工作上密切配合,從創(chuàng)業(yè)型企業(yè)到如今不斷成長(zhǎng),要感謝客戶對(duì)我們的高要求,讓我們敢于面對(duì)挑戰(zhàn),才有今天的進(jìn)步與發(fā)展。從網(wǎng)站到小程序開(kāi)發(fā),軟件開(kāi)發(fā),重慶APP開(kāi)發(fā),10年企業(yè)網(wǎng)站建設(shè)服務(wù)經(jīng)驗(yàn),為企業(yè)提供網(wǎng)站設(shè)計(jì),網(wǎng)站運(yùn)營(yíng)一條龍服務(wù).為企業(yè)提供全網(wǎng)營(yíng)銷推廣,按需策劃,原創(chuàng)設(shè)計(jì),10年品質(zhì),值得您的信賴.
引用泛型之后,允許制定集合里元素的類型,免去了強(qiáng)制類型轉(zhuǎn)換,并且能在編譯時(shí)刻進(jìn)行類型檢查的好處。
Parameterized Type 作為參數(shù)和返回值, Generic是vararg、annotation、enumeration、collection的基石。
拋棄List、Map,使用List<T>、Map<K,V>,給它們添加元素或者使用Iterator<T>遍歷時(shí),編譯期就可以給你檢查出類型錯(cuò)誤
拋棄List、Map,使用List<T>、Map<K,V>
List<String> list = new ArrayList<String>(); String str = list.get(i);
?
假設(shè)一個(gè)打印List<T>
中元素的方法printList
,我們希望任何類型T的List<T>都可以被打印, 代碼:
public void printList(List<?> list,PrintStream out)throws IOException{ for(Iterator<?> i=list.iterator();i.hasNext();){ System.out.println(i.next.toString()); } }
如果通配符?讓我們的參數(shù)類型過(guò)于廣泛,我們可以把List<?>、Iterator<?> 修改為L(zhǎng)ist<? Extends Number>、Iterator<? Extends Number>限制一下它。
簡(jiǎn)單的說(shuō)是類型自動(dòng)轉(zhuǎn)換。
自動(dòng)裝包:基本類型自動(dòng)轉(zhuǎn)為包裝類(int ——Integer)
自動(dòng)拆包:包裝類自動(dòng)轉(zhuǎn)為基本類型(Integer——int)
參數(shù)類型相同時(shí),把重載函數(shù)合并到一起了。
如:
public void test(object... objs){ for(Object obj:objs){ System.out.println(obj); } }
指出某個(gè)method覆蓋了superclass 的method當(dāng)你要覆蓋的方法名拼寫(xiě)錯(cuò)時(shí)編譯不通過(guò)
指出某個(gè)method或element類型的使用是被阻止的,子類將不能覆蓋該方法
關(guān)閉class、method、field、variable 初始化的編譯期警告,比如:List沒(méi)有使用 Generic,則@SuppressWarnings("unchecked")去掉編譯期警告。
public @interface Marked{}
或者說(shuō)annotation的annotation
四種標(biāo)準(zhǔn)的meta-annotation全部定義在java.lang.annotaion包中:
指定所定義的annotation可以用在哪些程序單元上,如果Target沒(méi)有指定,則表示該annotation可以使用在任意程序單元上
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface RejectEmpty { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD, ElementType.METHOD }) public @interface AcceptInt { int min() default Integer.MIN_VALUE; int max() default Integer.MAX_VALUE; String hint() default ""; }
指出Java編譯期如何對(duì)待annotation,annotation可以被編譯期丟掉,或者保留在編譯過(guò)的class文件中,在annotation被保留時(shí),它也指定是否會(huì)在JVM加載class時(shí)讀取該annotation
代碼
@Retention(RetentionPolicy.SOURCE) // Annotation會(huì)被編譯期丟棄 public @interface TODO1 {} @Retention(RetentionPolicy.CLASS) // Annotation保留在class文件中,但會(huì)被JVM忽略 public @interface TODO2 {} @Retention(RetentionPolicy.RUNTIME) // Annotation保留在class文件中且會(huì)被JVM讀取 public @interface TODO3 {}
指出被定義的annotation被視為所熟悉的程序單元的公開(kāi)API之一。被@Documented標(biāo)注的annotation會(huì)在javadoc中顯示,這在annotation對(duì)它標(biāo)注的元素被客戶端使用時(shí)有影響時(shí)起作用
該meta-annotation應(yīng)用于目標(biāo)為class的annotation類型上,被此annotattion標(biāo)注的class會(huì)自動(dòng)繼承父類的annotation
我們發(fā)現(xiàn)java.lang.Class有許多與Annotation的反射相關(guān)的方法,如getAnnotations、isAnnotationpresent。我們可以利用Annotation反射來(lái)做許多事情,比如自定義Annotation來(lái)做Model對(duì)象驗(yàn)證
代碼
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface RejectEmpty { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target( { ElementType.FIELD, ElementType.METHOD }) public @interface AcceptInt { int min() default Integer.MIN_VALUE; int max() default Integer.MAX_VALUE; String hint() default ""; }
使用@RejectEmpty和@AcceptInt標(biāo)注我們的Model的field,然后利用反射來(lái)做Model驗(yàn)證
formatter.format("Remaining account balance: $%.2f", balance);
HashMap的替代者ConcurrentHashMap和ArrayList的替代者CopyOnWriteArrayList
在大并發(fā)量讀取時(shí)采用java.util.concurrent包里的一些類會(huì)讓大家滿意BlockingQueue、Callable、Executor、Semaphore...
String s = "test"; switch (s) { case "test" : System.out.println("test"); case "test1" : System.out.println("test1"); break ; default : System.out.println("break"); break ; }
final List<Integer> piDigits = [ 1,2,3,4,5,8 ];
File System.getJavaIoTempDir() // IO臨時(shí)文件夾 File System.getJavaHomeDir() // JRE的安裝目錄 File System.getUserHomeDir() // 當(dāng)前用戶目錄 File System.getUserDir() // 啟動(dòng)java進(jìn)程時(shí)所在的目錄5
Boolean Booleans.negate(Boolean booleanObj) True => False , False => True, Null => Null boolean Booleans.and(boolean[] array) boolean Booleans.or(boolean[] array) boolean Booleans.xor(boolean[] array) boolean Booleans.and(Boolean[] array) boolean Booleans.or(Boolean[] array) boolean Booleans.xor(Boolean[] array)
boolean Character.equalsIgnoreCase(char ch2, char ch3)
int Math.safeToInt(long value) int Math.safeNegate(int value) long Math.safeSubtract(long value1, int value2) long Math.safeSubtract(long value1, long value2) int Math.safeMultiply(int value1, int value2) long Math.safeMultiply(long value1, int value2) long Math.safeMultiply(long value1, long value2) long Math.safeNegate(long value) int Math.safeAdd(int value1, int value2) long Math.safeAdd(long value1, int value2) long Math.safeAdd(long value1, long value2) int Math.safeSubtract(int value1, int value2)
java8的新特新逐一列出,并將使用簡(jiǎn)單的代碼示例來(lái)指導(dǎo)你如何使用默認(rèn)接口方法,lambda表達(dá)式,方法引用以及多重Annotation,之后你將會(huì)學(xué)到最新的API上的改進(jìn),比如流,函數(shù)式接口,Map以及全新的日期API
Java 8允許我們給接口添加一個(gè)非抽象的方法實(shí)現(xiàn),只需要使用default關(guān)鍵字即可,這個(gè)特征又叫做擴(kuò)展方法,示例如下:
interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } }
Formula接口在擁有calculate方法之外同時(shí)還定義了sqrt方法,實(shí)現(xiàn)了Formula接口的子類只需要實(shí)現(xiàn)一個(gè)calculate方法,默認(rèn)方法sqrt將在子類上可以直接使用。
Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0
文中的formula被實(shí)現(xiàn)為一個(gè)匿名類的實(shí)例,該代碼非常容易理解,6行代碼實(shí)現(xiàn)了計(jì)算 sqrt(a * 100)。在下一節(jié)中,我們將會(huì)看到實(shí)現(xiàn)單方法接口的更簡(jiǎn)單的做法。譯者注: 在Java中只有單繼承,如果要讓一個(gè)類賦予新的特性,通常是使用接口來(lái)實(shí)現(xiàn),在C++中支持多繼承,允許一個(gè)子類同時(shí)具有多個(gè)父類的接口與功能,在其他語(yǔ)言中,讓一個(gè)類同時(shí)具有其他的可復(fù)用代碼的方法叫做mixin。新的Java8的這個(gè)特新在編譯器實(shí)現(xiàn)的角度上來(lái)說(shuō)更加接近Scala的trait。在C#中也有名為擴(kuò)展方法的概念,允許給已存在的類型擴(kuò)展方法,和Java 8的這個(gè)在語(yǔ)義上有差別。
首先看看在老版本的Java中是如何排列字符串的:
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); } });
只需要給靜態(tài)方法 Collections.sort傳入一個(gè)List對(duì)象以及一個(gè)比較器來(lái)按指定順序排列。通常做法都是創(chuàng)建一個(gè)匿名的比較器對(duì)象然后將其傳遞給sort方法。在Java 8中你就沒(méi)必要使用這種傳統(tǒng)的匿名對(duì)象的方式了,Java 8提供了更簡(jiǎn)潔的語(yǔ)法,lambda表達(dá)式:
Collections.sort(names, (String a, String b) -> { return b.compareTo(a); });
看到了吧,代碼變得更段且更具有可讀性,但是實(shí)際上還可以寫(xiě)得更短:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
看到了吧,代碼變得更段且更具有可讀性,但是實(shí)際上還可以寫(xiě)得更短:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
對(duì)于函數(shù)體只有一行代碼的,你可以去掉大括號(hào){}以及return關(guān)鍵字,但是你還可以寫(xiě)得更短點(diǎn):
Collections.sort(names, (a, b) -> b.compareTo(a));
Java編譯器可以自動(dòng)推導(dǎo)出參數(shù)類型,所以你可以不用再寫(xiě)一次類型。
Lambda表達(dá)式是如何在java的類型系統(tǒng)中表示的呢?每一個(gè)lambda表達(dá)式都對(duì)應(yīng)一個(gè)類型,通常是接口類型。而“函數(shù)式接口”是指僅僅只包含一個(gè)抽象方法的接口,每一個(gè)該類型的lambda表達(dá)式都會(huì)被匹配到這個(gè)抽象方法。因?yàn)?默認(rèn)方法 不算抽象方法,所以你也可以給你的函數(shù)式接口添加默認(rèn)方法。
我們可以將lambda表達(dá)式當(dāng)作任意只包含一個(gè)抽象方法的接口類型,確保你的接口一定達(dá)到這個(gè)要求,你只需要給你的接口添加 @FunctionalInterface 注解,編譯器如果發(fā)現(xiàn)你標(biāo)注了這個(gè)注解的接口有多于一個(gè)抽象方法的時(shí)候會(huì)報(bào)錯(cuò)的。
@FunctionalInterface interface Converter<F, T> { T convert(F from); } Converter<String, Integer> converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123
需要注意如果@FunctionalInterface如果沒(méi)有指定,上面的代碼也是對(duì)的。
譯者注 將lambda表達(dá)式映射到一個(gè)單方法的接口上,這種做法在Java 8之前就有別的語(yǔ)言實(shí)現(xiàn),比如Rhino JavaScript解釋器,如果一個(gè)函數(shù)參數(shù)接收一個(gè)單方法的接口而你傳遞的是一個(gè)function,Rhino 解釋器會(huì)自動(dòng)做一個(gè)單接口的實(shí)例到function的適配器,典型的應(yīng)用場(chǎng)景有 org.w3c.dom.events.EventTarget 的addEventListener 第二個(gè)參數(shù) EventListener。
前一節(jié)中的代碼還可以通過(guò)靜態(tài)方法引用來(lái)表示:
Converter<String, Integer> converter = Integer::valueOf; Integer converted = converter.convert("123"); System.out.println(converted); // 123
Java 8 允許你使用::
關(guān)鍵字來(lái)傳遞方法或者構(gòu)造函數(shù)引用,上面的代碼展示了如何引用一個(gè)靜態(tài)方法,我們也可以引用一個(gè)對(duì)象的方法:
converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted); // "J"
接下來(lái)看看構(gòu)造函數(shù)是如何使用::
關(guān)鍵字來(lái)引用的,首先我們定義一個(gè)包含多個(gè)構(gòu)造函數(shù)的簡(jiǎn)單類:
class Person { String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } }
接下來(lái)我們指定一個(gè)用來(lái)創(chuàng)建Person對(duì)象的對(duì)象工廠接口:
interface PersonFactory<P extends Person> { P create(String firstName, String lastName); }
這里我們使用構(gòu)造函數(shù)引用來(lái)將他們關(guān)聯(lián)起來(lái),而不是實(shí)現(xiàn)一個(gè)完整的工廠:
PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("Peter", "Parker");
我們只需要使用Person::new
來(lái)獲取Person類構(gòu)造函數(shù)的引用,Java編譯器會(huì)自動(dòng)根據(jù)PersonFactory.create方法的簽名來(lái)選擇合適的構(gòu)造函數(shù)。
在lambda表達(dá)式中訪問(wèn)外層作用域和老版本的匿名對(duì)象中的方式很相似。你可以直接訪問(wèn)標(biāo)記了final的外層局部變量,或者實(shí)例的字段以及靜態(tài)變量。
我們可以直接在lambda表達(dá)式中訪問(wèn)外層的局部變量:
final int num = 1; Converter<Integer, String> stringConverter =(from) -> String.valueOf(from + num); stringConverter.convert(2); // 3
但是和匿名對(duì)象不同的是,這里的變量num可以不用聲明為final,該代碼同樣正確:
int num = 1; Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); stringConverter.convert(2); // 3
不過(guò)這里的num必須不可被后面的代碼修改(即隱性的具有final的語(yǔ)義),例如下面的就無(wú)法編譯:
int num = 1; Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num); num = 3;
在lambda表達(dá)式中試圖修改num同樣是不允許的。
和本地變量不同的是,lambda內(nèi)部對(duì)于實(shí)例的字段以及靜態(tài)變量是即可讀又可寫(xiě)。該行為和匿名對(duì)象是一致的:
class Lambda4 { static int outerStaticNum; int outerNum; void testScopes() { Converter<Integer, String> stringConverter1 = (from) -> { outerNum = 23; return String.valueOf(from); }; Converter<Integer, String> stringConverter2 = (from) -> { outerStaticNum = 72; return String.valueOf(from); }; } }
還記得第一節(jié)中的formula例子么,接口Formula定義了一個(gè)默認(rèn)方法sqrt可以直接被formula的實(shí)例包括匿名對(duì)象訪問(wèn)到,但是在lambda表達(dá)式中這個(gè)是不行的。
Lambda表達(dá)式中是無(wú)法訪問(wèn)到默認(rèn)方法的,以下代碼將無(wú)法編譯:
Formula formula = (a) -> sqrt( a * 100); Built-in Functional Interfaces
JDK 1.8 API包含了很多內(nèi)建的函數(shù)式接口,在老Java中常用到的比如Comparator或者Runnable接口,這些接口都增加了@FunctionalInterface注解以便能用在lambda上。
Java 8 API同樣還提供了很多全新的函數(shù)式接口來(lái)讓工作更加方便,有一些接口是來(lái)自Google Guava庫(kù)里的,即便你對(duì)這些很熟悉了,還是有必要看看這些是如何擴(kuò)展到lambda上使用的。
Predicate 接口只有一個(gè)參數(shù),返回boolean類型。該接口包含多種默認(rèn)方法來(lái)將Predicate組合成其他復(fù)雜的邏輯(比如:與,或,非):
Predicate<String> predicate = (s) -> s.length() > 0; predicate.test("foo"); // true predicate.negate().test("foo"); // false Predicate<Boolean> nonNull = Objects::nonNull; Predicate<Boolean> isNull = Objects::isNull; Predicate<String> isEmpty = String::isEmpty; Predicate<String> isNotEmpty = isEmpty.negate();
Function 接口有一個(gè)參數(shù)并且返回一個(gè)結(jié)果,并附帶了一些可以和其他函數(shù)組合的默認(rèn)方法(compose, andThen):
Function<String, Integer> toInteger = Integer::valueOf; Function<String, String> backToString = toInteger.andThen(String::valueOf); backToString.apply("123"); // "123"
Supplier 接口返回一個(gè)任意范型的值,和Function接口不同的是該接口沒(méi)有任何參數(shù)
Supplier<Person> personSupplier = Person::new; personSupplier.get(); // new Person
Consumer 接口表示執(zhí)行在單個(gè)參數(shù)上的操作。
Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName); greeter.accept(new Person("Luke", "Skywalker"));
Comparator 是老Java中的經(jīng)典接口, Java 8在此之上添加了多種默認(rèn)方法:
Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName); Person p1 = new Person("John", "Doe"); Person p2 = new Person("Alice", "Wonderland"); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0
Optional 不是函數(shù)是接口,這是個(gè)用來(lái)防止NullPointerException異常的輔助類型,這是下一屆中將要用到的重要概念,現(xiàn)在先簡(jiǎn)單的看看這個(gè)接口能干什么:
Optional 被定義為一個(gè)簡(jiǎn)單的容器,其值可能是null或者不是null。在Java 8之前一般某個(gè)函數(shù)應(yīng)該返回非空對(duì)象但是偶爾卻可能返回了null,而在Java 8中,不推薦你返回null而是返回Optional。
Optional<String> optional = Optional.of("bam"); optional.isPresent(); // true optional.get(); // "bam" optional.orElse("fallback"); // "bam" optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"
java.util.Stream 表示能應(yīng)用在一組元素上一次執(zhí)行的操作序列。Stream 操作分為中間操作或者最終操作兩種,最終操作返回一特定類型的計(jì)算結(jié)果,而中間操作返回Stream本身,這樣你就可以將多個(gè)操作依次串起來(lái)。Stream 的創(chuàng)建需要指定一個(gè)數(shù)據(jù)源,比如 java.util.Collection的子類,List或者Set, Map不支持。Stream的操作可以串行執(zhí)行或者并行執(zhí)行。
首先看看Stream是怎么用,首先創(chuàng)建實(shí)例代碼的用到的數(shù)據(jù)List:
List<String> stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1");
Java 8擴(kuò)展了集合類,可以通過(guò) Collection.stream() 或者 Collection.parallelStream() 來(lái)創(chuàng)建一個(gè)Stream。下面幾節(jié)將詳細(xì)解釋常用的Stream操作:
過(guò)濾通過(guò)一個(gè)predicate接口來(lái)過(guò)濾并只保留符合條件的元素,該操作屬于中間操作,所以我們可以在過(guò)濾后的結(jié)果來(lái)應(yīng)用其他Stream操作(比如forEach)。forEach需要一個(gè)函數(shù)來(lái)對(duì)過(guò)濾后的元素依次執(zhí)行。forEach是一個(gè)最終操作,所以我們不能在forEach之后來(lái)執(zhí)行其他Stream操作。
stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa2", "aaa1"
排序是一個(gè)中間操作,返回的是排序好后的Stream。如果你不指定一個(gè)自定義的Comparator則會(huì)使用默認(rèn)排序。
stringCollection .stream() .sorted() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); // "aaa1", "aaa2"
關(guān)于Java5、Java6、Java7、Java8的新特性是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
分享文章:Java5、Java6、Java7、Java8的新特性是什么
本文路徑:http://aaarwkj.com/article36/pesisg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、微信公眾號(hào)、軟件開(kāi)發(fā)、服務(wù)器托管、品牌網(wǎng)站設(shè)計(jì)、面包屑導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)