Java泛型枚舉Annotation接口詳細解讀與Eclipse發(fā)展
1、Eclipse開發(fā)工具
1.1 Eclipse歷史
Eclipse中文翻譯為日蝕,指的是吞沒一切的光芒,那么這個及其具備挑釁一位的名字實際上是針對于SU年公司。在2000年之后一直處于互聯(lián)網(wǎng)低潮,而SUN公司從這一低潮之后就再也沒有起來過,而后SUN公司最為尷尬的是,他在硬件上沒有過多的收益,而且軟件的編程語言Java也不是SUN的賺錢工具,它只是變成了一個出賣版權(quán)的公司了。
對于Java的IDE(集成開發(fā)環(huán)境)本身也是經(jīng)過了一些歷史的調(diào)整。
1995年的時候,Java誕生,但是SUN公司卻高調(diào)宣布,我們自己不生成IDE,給其他第三方公司生產(chǎn);
在Java產(chǎn)生之后,Borland公司來時入手Java的IDE生產(chǎn),所以后來的JBuilder就成為了Java開發(fā)的唯一選擇(不選擇JBuilder都使用記事本,IDEA,JCREATOR,EDIPLUS….),后倆一直到了JBuilderX之后才正常;
2003年之后有了Eclipse,在2004年之后有了SUN自己的開發(fā)工具———NetBeans
而從整個國內(nèi)的Java開發(fā)模式上也一直在發(fā)生著改變;
豪華級架構(gòu):操作系統(tǒng)+數(shù)據(jù)庫+中間件+開發(fā)工具+編程語言;
IBM體系:AIX+IBM DB2+WwbsphereApplicationServer+WSAD;
超級雜牌軍體系:UNIX+Oracle+Weblogic+JBuilder;
免費架構(gòu):Linux+MySQL+Tomcat/JBoss+Eclipse;
而對于開發(fā)工具最早的霸主就是JBuilder,但是遺憾的是,2006年的時候Borland倒閉了,倒閉的原因是因為沒有干聲多為的開源風潮,因為有許多的學習者,它可能并不需要如此專業(yè)的工具,所以當時Borland公司的市場就出現(xiàn)了問題,于是倒閉就成為了必然,最后Borland技術(shù)部單獨成立了一家技術(shù)公司,繼續(xù)從事JBuilder的研究,但是今天的JBuilder已經(jīng)基本上無法去問津了,完全被Eclipse取代了。
Eclipse是由IBM開發(fā)的,之后將其轉(zhuǎn)送給了今天的Eclipse組織,進行開源項目的推廣,而Eclipse的前身是IBM VisualAge,而后IBM根據(jù)Eclipse的1.0模型,產(chǎn)生后來的WSAD來發(fā)工具。Eclipse本身是免費的,但是其是靠插件收費(中國連插件都不需要收費),其本身有一下幾個基本組成:JDT,JUNIT測試工具,CVS客戶端,插件開發(fā),用戶可以直接登陸www.eclipse.org下載Eclipse的最新版本,JUNO(朱諾,小行星的名字)版,而且Eclipse現(xiàn)在可以直接解壓縮后使用,不用單獨的安裝,是純粹的綠色版。
當我們Java項目簡歷完成值周,可以在項目的目錄小發(fā)現(xiàn)兩個文件夾:
Src:是保存所有的*.java程序,都是按照包名稱進行保存的;
Bin:保存所有生成的*.class文件,按照包名稱進行保存的。
下面簡歷一個新的類:TestDemo.java
使用Eclipse本身最大的好處在于方便的進行隨筆提示,并且在每一次*.java程序保存的時候,會由Eclipse自動的將其編譯為*.class文件。
另外在Eclipse之中還可以存在一些代碼生成工具,例如:現(xiàn)在有如下簡單類
package com.sxau;
public class Person {
private String name;
private int age;
}
這個類肯定是作為簡單Java類出現(xiàn),那么現(xiàn)在很明顯簡單Java類的開發(fā)原則:
所有屬性封裝,已經(jīng)封裝;生成setter,getter方法;構(gòu)造方法,必須要有無參構(gòu)造覆寫Object中的一些方法
1.2 快捷鍵
除了以上的生成方式還可以通過快捷鍵生成
ALT+/:代碼自動補充提示;CTRL+1:進行錯誤代碼矯正提示;CTRL+D:刪除當前行代碼;CTRL+SHIFT+O:自動導入包;CTRL+SHIFT+F:格式化代碼顯示;CTRL+/:注釋/取消注釋;CTRL+shift+l:快捷鍵列表CTRL+H:搜索
項目也可以進行刪除操作,但是在刪除項目的時候有兩種方式:
方式一:是從項目的工作區(qū)之中刪除,以后可以恢復;
方式二:徹底從硬盤上刪除項目。
如果想導入項目則可以使用導入的方式。
以上是利用導入的方式完成了項目的導入,而現(xiàn)在也可以通過導出的方式,將一個項目之中的所有*.class文件自動生成*.jar文件。
1.3 Debug調(diào)試
在Eclipse之中,為了方便永華的開發(fā),還提供了DEBUG功能,可以利用此功能進行項目的調(diào)試操作,而如果要想進行調(diào)試,首先需要設置斷點。斷點指的是程序執(zhí)行到此處的時候,自動停止,而后交給人工控制執(zhí)行。
**范例:**設置斷點
package com.util;
public class MyMath {
private MyMath(){}
public static int add(int x, int y){
int temp = 0;
temp = x + y;
return temp;
}
}
測試類
package com.test;
import com.util.MyMath;
public class TestMath {
public static void main(String[] args) {
int result = MyMath.add(2, 3);//將此處設置為斷電
System.out.println("加法結(jié)果" + result);
}
}

進入調(diào)試試圖之后可以通過以下方式進行代碼調(diào)試:
- 單步跳入(F5):進入到代碼之中觀察代碼的執(zhí)行;
- 單步跳過(F6):不關(guān)心代碼之中的執(zhí)行,只關(guān)心最終的結(jié)果;
- 單步返回(F7):返回到單步跳過的狀態(tài)
- 恢復執(zhí)行(F8):不再調(diào)試直接將程序運行完成。
1.4 JUNIT測試工具
軟件測試行業(yè):2003年——2006年之后,各個公司一直都在招聘軟件測試人員,而且都是外包到IBM或微軟的公司進行測試。但是,今天的軟件測試來講,這個行業(yè)已經(jīng)很難了。
軟件測試是一個黃金職位,對于軟件測試是需要有一套完整測試理論和數(shù)據(jù)設計的,而如果學習過軟件工程應該知道軟件測試分為兩類:
1 黑盒測試:主要是測試功能,例如一些xx版,是不接觸代碼的,但是公司會提供工具;
2 白盒測試:指的是性能測試,或者是算法調(diào)整。
而這幾年隨著行業(yè)的發(fā)展,實際上又給出了一種新的測試職位——Use Case(用測)測試工程師,對于這種職位而言,國內(nèi)的平均待遇是程序員的3-5倍,如果按照正常的一個程序員的工資是8000來算,那么這種人的平均工資就是2-5萬,但是人很難難找,一般而言此類人員在行業(yè)中需要8-10年的項目經(jīng)驗,并且精通業(yè)務。
JUNIT是一個比較常用的測試工具,準們可以進行Use Case測試的,在日后所開發(fā)的程序里都要寫大量的JUNIT測試程序。
**范例:**定義要測試的程序
package com.util;
public class MyMath {
private MyMath(){}
public static int add(int x, int y){
int temp = 0;
temp = x + y;
return temp;
}
}
測試類
package com.test;
import static org.junit.Assert.*;
import org.junit.Test;
import com.util.MyMath;
import junit.framework.TestCase;
public class MyMathTest {
@Test
public void testAdd() {
TestCase.assertEquals(MyMath.add(2, 3), 5);
}
}
建立JUNIT測試的時候有兩種形式:
1.JUNIT Test Case:表示一個測試用例,主要完成一個業(yè)務的測試;
2.JUNIT Test Case:表示一組測試用例,包含多個Test Case。
對于JUNIT的測試結(jié)果來說,一共分為兩種:
1.GREEM BAR:測試通過;
2.RED BAR:測試失敗。
2、Java基礎新特性
Java的發(fā)展從1995年開始經(jīng)歷了許多的過程,但是有三個最具有代表性的JDK版本;
JDK1.0:標志著java的誕生;
JDK1.2:加入了javax.swing組件,這是主要新特性;
JDK1.5:標記為tiger,出現(xiàn)了許多一直沿用至今的特性;
JDK1.8:Lambda表達式、接口的定義加強
已經(jīng)接觸過了一些新特性,例如:自動裝箱與拆箱、switch對String的判斷支持。
2.1 可變參數(shù)
在講解可變參數(shù)之前,首先思考一個問題:如果說現(xiàn)在要實現(xiàn)若干個整型變量的相加操作,問,此方法該如何設計?使用數(shù)組接收,因為參數(shù)個數(shù)不確定,按照之前所學,只能使用數(shù)組完成。
package com.demo;
/**
* @author 張晟睿
*
*/
public class TestDemo {
public static void main(String[] args) {
System.out.println(add(new int[]{1}));
System.out.println(add(new int[]{1,2,3}));
System.out.println(add(new int[]{1,2,3,4,5,6,7}));
}
/**
* 實現(xiàn)任意個數(shù)的數(shù)據(jù)相加操作處理
* @param data相加操作數(shù)據(jù)
* @return 返回多個數(shù)據(jù)的相加結(jié)果
*/
public static int add(int [] data){
int sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i];
}
return sum;
}
}
以上的確是實現(xiàn)了技術(shù)要求,但是現(xiàn)在有一個新的問題產(chǎn)生了:如果按照題目要求,應該是可以任意的傳遞多個數(shù)據(jù),但是以上實際上傳的是一個數(shù)據(jù),只不過一個數(shù)據(jù)使用數(shù)組的形式封裝。那么為了更好的解決這個問題,可以使用JDK1.5的可變參數(shù)的方式來解決此問題
Public [static] [final] 返回值類型 方法名稱(參數(shù)類型…變量){ //雖然方式改變了
[return [返回值];]
}
發(fā)現(xiàn)現(xiàn)在進行方法參數(shù)的定義的時候有了一些變化,而這個時候的參數(shù)可以說是數(shù)組形式。
package com.demo;
/**
* @author 張晟睿
*
*/
public class TestDemo {
public static void main(String[] args) {
System.out.println(add(1));
System.out.println(add(1,2,3));
System.out.println(add(1,2,3,4,5,6,7));
}
/**
* 實現(xiàn)任意個數(shù)的數(shù)據(jù)相加操作處理
* @param data相加操作數(shù)據(jù)
* @return 返回多個數(shù)據(jù)的相加結(jié)果
*/
public static int add(int ... data){
int sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i];
}
return sum;
}
}
有了可變參數(shù)在日后進行方法調(diào)用的過程之中,就可以比較直觀的傳遞任意多個參數(shù),但是異常的操作在開發(fā)之中不建議使用,最好別用。
2.2 foreach輸出
首先需要解釋的是:foreach并不是新的概念,最早是在NET中提出來的,多為foreach可以理解為增強型的for循環(huán),下面來回顧一下最早的for循環(huán):
package com.demo;
/**
* @author 張晟睿
*
*/
public class TestDemo {
public static void main(String[] args) {
System.out.println(add(1));
System.out.println(add(1,2,3));
System.out.println(add(1,2,3,4,5,6,7));
}
/**
* 實現(xiàn)任意個數(shù)的數(shù)據(jù)相加操作處理
* @param data相加操作數(shù)據(jù)
* @return 返回多個數(shù)據(jù)的相加結(jié)果
*/
public static int add(int ... data){//接收原始數(shù)組
int sum = 0;
for (int i : data) { //將數(shù)組中的每一個元素設置給x
sum += i;//這種循環(huán)避免了腳標的問題
}
return sum;
}
}
但是有了foreach之后,那么對于數(shù)組或者是集合的輸出就有了新的支持,語法如下:
for(數(shù)據(jù)類型 變量 :數(shù)組|集合){
//操作代碼
}
對于這種for循環(huán)避免了數(shù)組越界的問題,但依然只是要求會使用,能看懂就行,不過個人建議:最好別用。
2.3 靜態(tài)導入
如果說想在想要導入一個不同包的類的方法,那么肯定使用import完成,即:如下是之前所采用的格式。
定義一個MyMath類
package com.util;
public class MyMath {
private MyMath(){}
public static int add(int x, int y){
int temp = 0;
temp = x + y;
return temp;
}
public static int sub(int x,int y){
return x-y;
}
public static int mul(int x,int y){
return x*y;
}
public static int div(int x,int y){
return x/y;
}
}
在JDK1.5值周,如果一個雷之中的全部方法都是static型的,則可以使用如下的語法進行導入:
import static 包.類.*;
表示的是將這個指定類之中的全部方法導入進來,最后就好像這些方法全部都是在主類之中定義的一樣。
package com.test;
import static com.util.MyMath.*;//靜態(tài)導入
public class TestMath {
public static void main(String[] args) {
System.out.println(add(10,20));
System.out.println(sub(30,10));
}
}
這種比較難受的方法,也只是出現(xiàn)在講課之中,本人是絕對不會使用的,你們也可以忘記它。
3、 JDK三大主要特性——泛型
泛型可以幫助我們解決參數(shù)轉(zhuǎn)換的問題
3.1 泛型的引出
下面首先通過一個簡單分析來研究一下泛型出現(xiàn)的主要目的是什么?例如現(xiàn)在要求定義一個表示坐標的操作類(Point)這個類可以表示三種類型的坐標:
整數(shù)坐標:x=10、y=20;
小數(shù)坐標:x=10.1、y=20.3;
字符串數(shù)據(jù):x=“東經(jīng)10度”、y=“西經(jīng)20度”。
類之中如果想要表示以上的數(shù)據(jù),一定需要定義x和y兩個屬性,而且每一個屬性可以接收三種數(shù)據(jù)類型,那么只能使用Object類來定義會比較合適,這樣會發(fā)生如下的幾種轉(zhuǎn)換關(guān)系:
整數(shù):int→自動裝箱為Integer→向上轉(zhuǎn)型為Object;
小數(shù):double→自動裝箱為Double→向上轉(zhuǎn)型為Obejct;
字符串:字符串→向上轉(zhuǎn)型為Obejct;
設置整形
package com.demo;
class Point {
private Object x;
private Object y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
public class PointDemo {
public static void main(String[] args) {
//第一步:設置數(shù)據(jù)
Point p = new Point();
p.setX(10);
p.setY(20);
//第二步:取出數(shù)據(jù)
int x = (Integer)p.getX();
int y = (Integer)p.getY();
System.out.println("x = " + x + ",y = " + y);
}
}
設置小數(shù)
package com.demo;
class Point {
private Object x;
private Object y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
public class PointDemo {
public static void main(String[] args) {
//第一步:設置數(shù)據(jù)
Point p = new Point();
p.setX(10.1);
p.setY(20.2);
//第二步:取出數(shù)據(jù)
double x = (Double)p.getX();
double y = (Double)p.getY();
System.out.println("x = " + x + ",y = " + y);
}
}
設置字符串
package com.demo;
class Point {
private Object x;
private Object y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
public class PointDemo {
public static void main(String[] args) {
//第一步:設置數(shù)據(jù)
Point p = new Point();
p.setX("東經(jīng)10");
p.setY("西經(jīng)20");
//第二步:取出數(shù)據(jù)
String x = (String)p.getX();
String y = (String)p.getY();
System.out.println("x = " + x + ",y = " + y);
}
}
看起來所有功能都實現(xiàn)了,并根據(jù)之前所學的內(nèi)容,也只能做到這些了,但是本程序還有一系列問題。
本程序解決問題的關(guān)鍵就在Object類,所有的類型都可以想Obejct轉(zhuǎn)換,但是成也是它敗也是它。
public class PointDemo {
public static void main(String[] args) {
Point point = new Point();
//設置參數(shù)
point.setX(10);
point.setY("北緯");
//取出參數(shù)
String x = (String) point.getX();
String y = (String) point.getY();
System.out.println("x的坐標是:"+x+"y的坐標是:"+y);
}
}
這個時候程序并沒有任何的語法錯誤,因為數(shù)字10 被包裝成了Integer,可以使用Obejct接收,從技術(shù)上而言,本操作沒有問題,但是從實際來講,因為沒有統(tǒng)一,多以在取得數(shù)據(jù)并且執(zhí)行向下轉(zhuǎn)型的過程中就會出現(xiàn)如下的錯誤提示信息:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at cn.mldn.demo.TestDemo.main(PointDemo.java:30)
所以,就可以得出一個結(jié)論,以上的程序存在安全隱患,但是并沒有在程序的編譯過程中檢查出來,而現(xiàn)在就可以利用泛型來解決這種問題。
3.2 泛型實現(xiàn)
泛型:類之中操作的屬性或方法的參數(shù)類型不在定義的時候聲明,而是在使用的時候動態(tài)設置。
package com.demo;
//在定義Point不知道是什么類型,由使用者來進行定義使用
class Point<T> {//T表示參數(shù),一個占位標記
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
public class PointDemo {
public static void main(String[] args) {
//第一步:設置數(shù)據(jù)
Point<String> p = new Point<String>();
p.setX("東經(jīng)10");
p.setY("西經(jīng)20");
//第二步:取出數(shù)據(jù)
String x = p.getX();//避免了向下轉(zhuǎn)型
String y = p.getY();
System.out.println("x = " + x + ",y = " + y);
}
}
測試沒有了向下轉(zhuǎn)型的操作關(guān)系,那么程序就避免了安全性的問題,而且如果設置的類型不統(tǒng)一,在程序編譯的過程之中也是可以很好的解決了,直接會報出語法錯誤。
而且當用戶在使用Point類聲明對象的時候沒有設置泛型,程序在編譯的過程之中,會提示警告信息,而且為了保證程序不出現(xiàn)錯誤,所有的類型都將使用Obejct進行處理。使用泛型可以很好的解決數(shù)據(jù)類型的統(tǒng)一問題。
但是在此處需要提醒的是,JDK1.5和JDK1.7在定義泛型的時候是稍微有些區(qū)別的。
JDK1.5的時候聲明泛型的操作
Point<String> p= new Point<String>();
以上是JDK1.5的語法,在聲明對象和實例化對象的時候都必須設置好泛型類型。
JDK1.7的時候簡化了
Point<String> p= new Point< >();
這個時候?qū)嵗瘜ο髸r泛型的泛型類型就通過聲明時泛型類型來定義了。
3.3 通配符
泛型的而出現(xiàn)的確是可以解決了數(shù)據(jù)的統(tǒng)一問題以及避免了向下轉(zhuǎn)型操作,但同事也會帶來新的問題,下面通過一段程序,來觀察一下會產(chǎn)生什么問題?
為了簡化定義一個簡單的泛型
package com.demo;
class Message<T>{
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
以上的類對象進行引用傳遞
public class MessageDemo {
public static void main(String[] args) {
Message<String> msg = new Message<>();
msg.setInfo("hello,world!");
print(msg);//以上的類對象進行引用傳遞
}
public static void print(Message<String> s){
System.out.println(s.getInfo());
}
}
但是如果現(xiàn)在定義的泛型類型不是String呢?例如:換成了int(不能是基本數(shù)據(jù)類型,只能是包裝類)
public class MessageDemo {
public static void main(String[] args) {
Message<Integer> msg = new Message<>();
msg.setInfo(100);
print(msg);//無法進行引用傳遞
}
public static void print(Message<String> s){
System.out.println(s.getInfo());
}
}
發(fā)現(xiàn)這個時候的print()方法無法再接收Message對象的引用,因為這個方法只能夠接收Message對象的引用,那么可以將print()方法重載換成Message
public class MessageDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Message<Integer> msg = new Message<>();
msg.setInfo(100);
print(msg);
}
public static void print(Message<String> msg){
System.out.println(msg.getInfo());
}
public static void print(Message<Integer> msg){
System.out.println(msg.getInfo());
}
}
這個時候發(fā)現(xiàn)按照之前的方式根本就無法進行方法的重載,方法的重載沒有說為一個類而定義的,因為方法重載的時候觀察的不是泛型類型,而是類的名稱,或者說是數(shù)據(jù)類型的,所以現(xiàn)在就可以發(fā)現(xiàn),這個給出了泛型類之后,就相當于將一個類又劃分成了幾個小類。

那么現(xiàn)在的問題:方法接收的參數(shù)問題又嚴重了,而且比之前使用對象多態(tài)性解決問題時出現(xiàn)的麻煩更大了,至少那個時候可以利用重載來接收一個類的所有子類對象,而現(xiàn)在連重載都使用不了。
這個時候,有人提出了,干脆在定義方法的時候就別寫泛型類型了。
定義方法的時候不定義泛型類型
public class MessageDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Message<Integer> msg = new Message<>();
msg.setInfo(100);
print(msg);
}
public static void print(Message msg){
System.out.println(msg.getInfo());
}
}
雖然現(xiàn)在print()方法的參數(shù)上出現(xiàn)了警告,但是現(xiàn)在的程序可算是正常了,但是新的問題又來了。問題就在于方法操作中,沒有類型限制了。
public static void print(Message msg){
msg.setInfo(100);
System.out.println(msg.getInfo());
}
發(fā)現(xiàn)此時在print()方法之中操作的時候,由于沒有設置泛型類型,那么所有類型都統(tǒng)一變?yōu)榱薕bject,也就可以修改了。而通過本程序也就發(fā)現(xiàn)了,必須找到一種方法,:此方法可以接收任意的泛型類型的設置,并且不能修改,只能輸出,為了解決這樣的問題,可以使用通配符“?”表示。
public static void print(Message<?> msg){
System.out.println(msg.getInfo());
}
由于“?”出現(xiàn)的情況較多,尤其在學習一些類庫的時候,所以對于“?”就記住一點,表示任意類型,如果有參數(shù)返回的時候也是這個“?”,當成Object進行理解。
既然現(xiàn)在談到了Obejct,那么現(xiàn)在實際上又有了另外一個問題:對于所有的子類,都是Object子類,那么如果對于之前的程序都使用Object能不能接收?
Message<String> msg = new Message<>(); Message<Object> s = msg;
因為Object的范圍比String的范圍大。
而在通配符“?”上有衍生出了兩個子符號:
設置泛型的上限:?extends 類;
例如:?extends Number,表示只能是Number或者是Number的子類Integer等;
2.設置泛型的下限:?super類;
例如:?super String,表示只能是String或者是String的父類(Object)
設置泛型上限
package com.demo;
class Message<T extends Number>{
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
public class MessageDemo {
public static void main(String[] args) {
Message<Integer> msg = new Message<>();
msg.setInfo(100);
//100
print(msg);
}
public static void print(Message<? extends Number> s){
System.out.println(s.getInfo());
}
}
設置泛型下限
package com.demo;
class Message<T>{
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
public class MessageDemo {
public static void main(String[] args) {
Message<String> msg = new Message<>();
msg.setInfo("Hello,world!100");
//Hello,world!100
print(msg);
}
//此時使用通配符“?”描述的是它可以接收任何任意數(shù)據(jù)類型,但是由于不確定類型,無法修改
public static void print(Message<? super String> s){
System.out.println(s.getInfo());
}
}
3.4 泛型接口
在之前的所有定義的泛型之中,都是在類上定義的,而對于接口也是可以進行泛型定義的,而使用泛型定義的接口可以稱為泛型接口。
interface Message<T>{
public String echo(T msg);
}
而對于泛型接口的實現(xiàn),在Java中有兩種方式:
方式一:在子類上繼續(xù)定義泛型,同時此泛型繼續(xù)在接口上使用
package com.test;
interface IMessage<T>{
public void print(T t);
}
class MessageImpl<T> implements IMessage<T>{
@Override
public void print(T t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class MessageTest {
public static void main(String[] args) {
IMessage<String> msgimpl = new MessageImpl();
msgimpl.print("Hello,world!!");
}
}
方式二:在子類上設置具體類型
package com.test;
interface IMessage<T>{
public void print(T t);
}
class MessageImpl implements IMessage<String>{
@Override
public void print(String t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class MessageTest {
public static void main(String[] args) {
IMessage<String> msgimpl = new MessageImpl();
msgimpl.print("Hello,world!!");
}
}
3.5 泛型方法
對于泛型除了可以在類上定義,也可以在方法上定義,而在方法上進行泛型的時候這個方法不一定非在泛型類中定義。
public class TestDemo {
public static void main(String[] args) {
// TODO 自動生成的方法存根
Integer result[] = get(1,2,3);
for(int temp : result){
System.out.println(temp);
}
}
public static <T> T[] get(T... date){
return date;
}
}
4、JDK三大主要特性——枚舉
在講解枚舉之前回顧一個概念:多例設計模式,構(gòu)造方法私有化(非public),之后在類的內(nèi)部存在若干個指定的對象,通過一個方法返回指定對象。
4.1 多例與枚舉
定義一個描述顏色基色的多例設計類
package com.demo;
class Color {
private static final Color RED = new Color("紅色");
private static final Color GREEN = new Color("綠色");
private static final Color BLUE = new Color("藍色");
private String title;
private Color(String title){
this.title=title;
}
public String toString(){
return this.title;
}
public static Color getColor(int num){
switch(num){
case 0:
return RED;
case 1:
return GREEN;
case 2:
return BLUE;
default:
return null;
}
}
}
public class ColorDemo {
public static void main(String[] args) {
Color c = Color.getColor(0);
System.out.println(c);
}
}
基于枚舉開發(fā)
package com.demo;
enum Color {
RED,BULE,PINK;
}
public class ColorDemo {
public static void main(String[] args) {
System.out.println(Color.RED);
}
}
4.2 Enum類
很明顯,現(xiàn)在可以發(fā)現(xiàn),利用枚舉實現(xiàn)多例設計會更加的簡單直白一些,但是在Java之中,枚舉并不是一個新的類型,嚴格來講,每一個使用enum定義的類實際上都屬于一個類繼承了Enum父類而已,而java.lang.Enum類定義如下:
public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable
而在Enum類種子紅定義了兩個方法:
取得枚舉的序號:public final int ordinal();
取得枚舉的名稱:public final String name()。
package com.demo;
enum Color {
RED,BULE,PINK;
}
public class ColorDemo {
public static void main(String[] args) {
//0===RED
System.out.println(Color.RED.ordinal() + "===" + Color.RED.name());
}
}
取得所有顏色數(shù)據(jù)
package com.demo;
enum Color {
RED,BULE,PINK;
}
public class ColorDemo {
public static void main(String[] args) {
/*0===RED
1===BULE
2===PINK*/
for (Color c : Color.values()) {
System.out.println(c.ordinal() + "===" + c.name());
}
}
}
面試題:請解釋enum和Enum的區(qū)別?
enum是一個關(guān)鍵字,使用enum定義的枚舉類本質(zhì)上相當于一個類繼承了Enum類而已。
4.3 枚舉中定義其它結(jié)構(gòu)
按照之前所理解,枚舉就屬于多例設計模式,那么既然是多例設計模式,對于類之中就肯定有多種組成,包括屬性,方法,構(gòu)造方法,在枚舉之中也同樣可以定義以上的內(nèi)容,不過需要注意的是,枚舉類之中定義的構(gòu)造方法絕對不能是public,必須私有化。
除了這些要求之外枚舉之中每一個定義的對象必須定義在第一行。
package com.demo;
enum Color {
RED("紅色"),BULE("藍色"),PINK("粉色");
private String c;
private Color(String c){
this.c = c;
}
public String toString(){
return this.c;
}
}
public class ColorDemo {
public static void main(String[] args) {
/*紅色*/
System.out.println(Color.RED);
}
}
枚舉接口
package com.demo;
interface IColor{
public String getColor();
}
enum Color implements IColor{
RED("紅色"),BULE("藍色"),PINK("粉色");
private String c;
private Color(String c){
this.c = c;
}
public String toString(){
return this.c;
}
@Override
public String getColor() {
// TODO Auto-generated method stub
return this.c;
}
}
public class ColorDemo {
public static void main(String[] args) {
/*紅色*/
System.out.println(Color.RED);
}
}
4.4 枚舉應用
只有指定的幾個對象
性別
package com.demo;
class Person{
private String name;
private int age;
private Sex sex;
public Person(String name, int age, Sex sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
enum Sex{
MALE("男"),FEMALE("女");
private String sex;
private Sex(String sex) {
this.sex = sex;
}
public String toString(){
return this.sex;
}
}
public class MaleDemo {
public static void main(String[] args) {
Person person = new Person("jack", 10, Sex.MALE);
System.out.println(person.toString());
}
}
枚舉還可以進行switch語句進行編寫和判斷。
5、JDK三大主要特性——Annotation
在JDK1.5之后,程序允許通過注解(Annotation)的方式來進行程序的定義,而在JavaSE之中攢在了三種Annotation:@Override、@Deprecated、@SuppressWarnings。
5.1 準確的覆寫:@Override
方法的覆寫:發(fā)生繼承關(guān)系之中,子類定義了與父類的方法名稱相同、參數(shù)類型以及個數(shù)相同的覆寫,被覆寫的方法不能夠擁有比父類更為嚴格的訪問控制權(quán)限。
package com.annotation;
class Person{
//現(xiàn)在是希望進行toString()覆寫,但遺憾的由于你自己的輸入錯誤,導致方法的覆寫錯誤
//@Override
public String tostring(){//現(xiàn)在希望可以進行toString()方法的覆寫
return "一個人";
}
}
public class Demo1 {
public static void main(String[] args) {
System.out.println(new Person().tostring());
}
}
這個時候不叫覆寫,屬于自己定義一個擴展的方法,最為重要的是,這個問題在程序編譯的根本就無法顯示出來。但是現(xiàn)在為了保證我們的覆寫方法的嚴格,可以使用一個注解(@Override)來檢測:如果該方法確定成的覆寫了
,則不會有我們的語法錯誤,如果進行成功的覆寫,認為語法的錯誤。
package com.annotation;
class Person{
//現(xiàn)在是希望進行toString()覆寫,但遺憾的由于你自己的輸入錯誤,導致方法的覆寫錯誤
public String toString(){//現(xiàn)在希望可以進行toString()方法的覆寫
return "一個人";
}
}
public class Demo1 {
public static void main(String[] args) {
System.out.println(new Person());
}
}
5.2 聲明過期操作:@Deprecated
對于程序開發(fā)而言,往往一些使用的類要進行修改或者是維護,如果說現(xiàn)在一個類之中的某個方法,可能一開始推出的時候正常使用,但是在后面的版本就存在了一些問題,在修改之后不希望人再去使用這些方法,那么肯定不能直接刪除,因為如果直接刪除了,那么之前的程序就會出現(xiàn)問題了,所以最好的做法是告訴用戶:這個方法存在了問題,不建議再使用了,這個時候就使用“@Deprecated”聲明。
package com.annotation;
class Person1{
@Deprecated//表示該方法不建議使用,即使使用仍然不會報錯
public Person1(){}
public Person1(String name){}
@Deprecated
public void print(){}
}
public class Demo2 {
public static void main(String[] args) {
Person1 person = new Person1();//明確標記過期
person.print();
}
}
5.3 壓制警告:@SuppressWarning
程序在編譯的時候如果提示警告但是不會報錯只是存在了某些安全隱患,肯定會提示用戶,所以不想讓其顯示的話,就增加壓制警告信息。
package com.annotation;
class Person1<T>{
@Deprecated//表示該方法不建議使用,即使使用仍然不會報錯
public Person1(){}
public Person1(String name){}
@Deprecated
public void print(){}
}
public class Demo2 {
@SuppressWarnings("rawtypes")
public static void main(String[] args) {
Person1 person = new Person1();//明確標記過期
person.print();
}
}

關(guān)于軟件的開發(fā)模式;
第一階段:會將所有的操作都寫在程序之中,例如:網(wǎng)絡程序,連接程序,連接的服務器地址,用戶驗證等;
第二階段:程序+配置文件,配置文件和程序相分離,配置文件過多,后期修改非常復雜;
第三階段:將配置文件寫回到程序之中,但是和程序進行有效的分離。
6、接口定義加強

造成此種尷尬的局面的核心問題在于,接口只是一個方法的聲明,而沒有具體方法的實現(xiàn),所以隨著時間的推移,如果出現(xiàn)以上的問題,該接口將無法繼續(xù)使用。從JDK1.8為了解決這個問題,專門提供兩種專門的接口。
可以使用default來定義普通方法,需要通過對象調(diào)用。可以使用static來定義靜態(tài)方法,通過接口名就能使用。
定義普通方法
package com.annotation;
interface IMess{
public default void fun(){//追加普通方法,又方法體了
System.out.println("hello,world!");
}
public void print();
}
class MessImpl implements IMess{
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println("www.baidu.com");
}
}
public class Demo3 {
public static void main(String[] args) {
MessImpl msg = new MessImpl();
msg.print();
msg.fun();
}
}
定義static方法
package com.annotation;
interface IMess{
public default void fun(){//追加普通方法,又方法體了
System.out.println("hello,world!");
}
public static IMess getInstance(){//定義靜態(tài)方法
return new MessImpl();
}
public void print();
}
class MessImpl implements IMess{
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println("www.baidu.com");
}
}
public class Demo3 {
public static void main(String[] args) {
// MessImpl msg = new MessImpl();
IMess msg = IMess.getInstance();
msg.print();
msg.fun();
}
}
整體來說,接口更像抽象類,但是比抽象類強大在于,接口的子類依然可以實現(xiàn)多繼承的關(guān)系,而抽象類繼續(xù)保持單繼承。
7、Lambda表達式
最具有代表性的就是haskell.函數(shù)式編程和面向?qū)ο缶幊虨閮纱箝_發(fā)陣營
傳統(tǒng)的面向?qū)ο箝_發(fā)
package com.annotation;
interface IMess{
public void print();
}
public class Demo3 {
public static void main(String[] args) {
IMess msg = new IMess(){
public void print(){
System.out.println("Hello,world!");
};
};
msg.print();
}
}
使用匿名內(nèi)部類來實現(xiàn)接口最大好處就是節(jié)約了一個文件,最大的缺點就是看的眼花繚亂,對于此操作有了更簡化的體現(xiàn)。如果采用函數(shù)式編程模型。
函數(shù)式編程模型
package com.annotation;
interface IMess{
public void print();
}
public class Demo3 {
public static void main(String[] args) {
IMess msg = ()->System.out.println("Hello,world!");
msg.print();
}
}
如果想要使用函數(shù)式編程前提,接口只能寫一個方法,如果編寫兩個方法,則會出現(xiàn)語法錯誤??梢栽诮涌诘拈_頭加上@FunctionalInterface聲明這是一個函數(shù)接口。
實際上對于以上的語法形式:
(參數(shù) )->單行語句;

這個時候方法本身只包含一行語句,那么直接編寫語句即可,如果要是有多行語句,則就需要我們使用"{}"
package com.annotation;
@FunctionalInterface
interface IMess{
public void print();
}
public class Demo3 {
public static void main(String[] args) {
IMess msg = ()->{
System.out.println("Hello,world!");
System.out.println("Hello,world!");
System.out.println("Hello,world!");
};
msg.print();
}
}
如果現(xiàn)在你的表達式里面的內(nèi)容只是一行進行數(shù)據(jù)的返回,那么直接使用語句即可,不用寫return。
package com.annotation;
interface IMath{
public int add(int x, int y);
}
public class Demo4 {
public static void main(String[] args) {
IMath msg = (p1, p2)-> p1 + p2;
System.out.println(msg.add(10, 20));
}
}
到此這篇關(guān)于Day11基礎不牢地動山搖-Java基礎的文章就介紹到這了,更多相關(guān)Java基礎內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實例講解Java的Spring框架中的控制反轉(zhuǎn)和依賴注入
這篇文章主要介紹了Java的Spring框架中的控制反轉(zhuǎn)和依賴注入,Spring是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-02-02
spring基于通用Dao的多數(shù)據(jù)源配置詳解
這篇文章主要為大家詳細介紹了spring基于通用Dao的多數(shù)據(jù)源配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下解2018-03-03
關(guān)于Java8新特性Optional類的詳細解讀
Optional類是一個容器類,它可以保存類型T的值,代表這個值存在?;蛘邇H僅保存null,表示這個值不存在,原來用 null 表示一個值不存在,現(xiàn)在Optional 可以更好的表達這個概念。并且可以避免空指針異常,需要的朋友可以參考下2023-05-05

