主頁 > 後端開發 > # Day11-Java基礎

# Day11-Java基礎

2021-08-18 07:53:28 後端開發

Day11-Java

文章目錄

  • Day11-Java
      • 1、Eclipse開發工具
          • 1.1 Eclipse歷史
          • 1.2 快捷鍵
          • 1.3 Debug除錯
          • 1.4 JUNIT測驗工具
      • 2、Java基礎新特性
          • 2.1 可變引數
          • 2.2 foreach輸出
          • 2.3 靜態匯入
      • 3、 JDK三大主要特性——泛型
          • 3.1 泛型的引出
          • 3.2 泛型實作
          • 3.3 通配符
          • 3.4 泛型介面
          • 3.5 泛型方法
      • 4、JDK三大主要特性——列舉
          • 4.1 多例與列舉
          • 4.2 Enum類
        • 面試題:請解釋enum和Enum的區別?
          • 4.3 列舉中定義其它結構
          • 4.4 列舉應用
      • 5、JDK三大主要特性——Annotation
          • 5.1 準確的覆寫:@Override
          • 5.2 宣告過期操作:@Deprecated
          • 5.3 壓制警告:@SuppressWarning
      • 6、介面定義加強
      • 7、Lambda運算式

1、Eclipse開發工具

1.1 Eclipse歷史

Eclipse中文翻譯為日蝕,指的是吞沒一切的光芒,那么這個及其具備挑釁一位的名字實際上是針對于SU年公司,在2000年之后一直處于互聯網低潮,而SUN公司從這一低潮之后就再也沒有起來過,而后SUN公司最為尷尬的是,他在硬體上沒有過多的收益,而且軟體的編程語言Java也不是SUN的賺錢工具,它只是變成了一個出賣著作權的公司了,

對于Java的IDE(集成開發環境)本身也是經過了一些歷史的調整,

? 1995年的時候,Java誕生,但是SUN公司卻高調宣布,我們自己不生成IDE,給其他第三方公司生產;

? 在Java產生之后,Borland公司來時入手Java的IDE生產,所以后來的JBuilder就成為了Java開發的唯一選擇(不選擇JBuilder都使用記事本,IDEA,JCREATOR,EDIPLUS….),后倆一直到了JBuilderX之后才正常;

? 2003年之后有了Eclipse,在2004年之后有了SUN自己的開發工具———NetBeans

而從整個國內的Java開發模式上也一直在發生著改變;

? 豪華級架構:作業系統+資料庫+中間件+開發工具+編程語言;

? IBM體系:AIX+IBM DB2+WwbsphereApplicationServer+WSAD;

? 超級雜牌軍體系:UNIX+Oracle+Weblogic+JBuilder;

免費架構:Linux+MySQL+Tomcat/JBoss+Eclipse;

而對于開發工具最早的霸主就是JBuilder,但是遺憾的是,2006年的時候Borland倒閉了,倒閉的原因是因為沒有干聲多為的開源風潮,因為有許多的學習者,它可能并不需要如此專業的工具,所以當時Borland公司的市場就出現了問題,于是倒閉就成為了必然,最后Borland技術部單獨成立了一家技術公司,繼續從事JBuilder的研究,但是今天的JBuilder已經基本上無法去問津了,完全被Eclipse取代了,

Eclipse是由IBM開發的,之后將其轉送給了今天的Eclipse組織,進行開源專案的推廣,而Eclipse的前身是IBM VisualAge,而后IBM根據Eclipse的1.0模型,產生后來的WSAD來發工具,Eclipse本身是免費的,但是其是靠插件收費(中國連插件都不需要收費),其本身有一下幾個基本組成:JDT,JUNIT測驗工具,CVS客戶端,插件開發,用戶可以直接登陸www.eclipse.org下載Eclipse的最新版本,JUNO(朱諾,小行星的名字)版,而且Eclipse現在可以直接解壓縮后使用,不用單獨的安裝,是純粹的綠色版,

當我們Java專案簡歷完成值周,可以在專案的目錄小發現兩個檔案夾:

? Src:是保存所有的*.java程式,都是按照包名稱進行保存的;

? Bin:保存所有生成的*.class檔案,按照包名稱進行保存的,

下面簡歷一個新的類:TestDemo.java

使用Eclipse本身最大的好處在于方便的進行隨筆提示,并且在每一次*.java程式保存的時候,會由Eclipse自動的將其編譯為*.class檔案,

另外在Eclipse之中還可以存在一些代碼生成工具,例如:現在有如下簡單類

package com.sxau;

public class Person {
	private String name;
	private int age;
}

這個類肯定是作為簡單Java類出現,那么現在很明顯簡單Java類的開發原則:

  1. 所有屬性封裝,已經封裝;
  2. 生成setter,getter方法;
  3. 構造方法,必須要有無參構造
  4. 覆寫Object中的一些方法
1.2 快捷鍵

除了以上的生成方式還可以通過快捷鍵生成

  1. ALT+/:代碼自動補充提示;
  2. CTRL+1:進行錯誤代碼矯正提示;
  3. CTRL+D:洗掉當前行代碼;
  4. CTRL+SHIFT+O:自動匯入包;
  5. CTRL+SHIFT+F:格式化代碼顯示;
  6. CTRL+/:注釋/取消注釋;
  7. CTRL+shift+l:快捷鍵串列
  8. CTRL+H:搜索

專案也可以進行洗掉操作,但是在洗掉專案的時候有兩種方式:

? 方式一:是從專案的作業區之中洗掉,以后可以恢復;

? 方式二:徹底從硬碟上洗掉專案,

如果想匯入專案則可以使用匯入的方式,

? 以上是利用匯入的方式完成了專案的匯入,而現在也可以通過匯出的方式,將一個專案之中的所有*.class檔案自動生成*.jar檔案,

1.3 Debug除錯

在Eclipse之中,為了方便永華的開發,還提供了DEBUG功能,可以利用此功能進行專案的除錯操作,而如果要想進行除錯,首先需要設定斷點,斷點指的是程式執行到此處的時候,自動停止,而后交給人工控制執行,

**范例:**設定斷點

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("加法結果" +  result);
	}
	
}

image-20210814103300051

進入除錯試圖之后可以通過以下方式進行代碼除錯:

  1. 單步跳入(F5):進入到代碼之中觀察代碼的執行;
  2. 單步跳過(F6):不關心代碼之中的執行,只關心最終的結果;
  3. 單步回傳(F7):回傳到單步跳過的狀態
  4. 恢復執行(F8):不再除錯直接將程式運行完成,
1.4 JUNIT測驗工具

軟體測驗行業:2003年——2006年之后,各個公司一直都在招聘軟體測驗人員,而且都是外包到IBM或微軟的公司進行測驗,但是,今天的軟體測驗來講,這個行業已經很難了,

軟體測驗是一個黃金職位,對于軟體測驗是需要有一套完整測驗理論和資料設計的,而如果學習過軟體工程應該知道軟體測驗分為兩類:

? 1 黑盒測驗:主要是測驗功能,例如一些xx版,是不接觸代碼的,但是公司會提供工具;

? 2 白盒測驗:指的是性能測驗,或者是演算法調整,

而這幾年隨著行業的發展,實際上又給出了一種新的測驗職位——Use Case(用測)測驗工程師,對于這種職位而言,國內的平均待遇是程式員的3-5倍,如果按照正常的一個程式員的工資是8000來算,那么這種人的平均工資就是2-5萬,但是人很難難找,一般而言此類人員在行業中需要8-10年的專案經驗,并且精通業務,

JUNIT是一個比較常用的測驗工具,準們可以進行Use Case測驗的,在日后所開發的程式里都要寫大量的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:表示一個測驗用例,主要完成一個業務的測驗;

? 2.JUNIT Test Case:表示一組測驗用例,包含多個Test Case,

對于JUNIT的測驗結果來說,一共分為兩種:

? 1.GREEM BAR:測驗通過;

? 2.RED BAR:測驗失敗,

2、Java基礎新特性

Java的發展從1995年開始經歷了許多的程序,但是有三個最具有代表性的JDK版本;

JDK1.0:標志著java的誕生;

JDK1.2:加入了javax.swing組件,這是主要新特性;

JDK1.5:標記為tiger,出現了許多一直沿用至今的特性;

JDK1.8:Lambda運算式、介面的定義加強

已經接觸過了一些新特性,例如:自動裝箱與拆箱、switch對String的判斷支持,

2.1 可變引數

在講解可變引數之前,首先思考一個問題:如果說現在要實作若干個整型變數的相加操作,問,此方法該如何設計?使用陣列接收,因為引數個數不確定,按照之前所學,只能使用陣列完成,

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}));
	}
	
 /**
 * 實作任意個數的資料相加操作處理
 * @param data相加操作資料
 * @return	回傳多個資料的相加結果
 */
public static int add(int [] data){
		int sum = 0;
		for (int i = 0; i < data.length; i++) {
			sum += data[i];
		}
		return sum;
	}
}

以上的確是實作了技術要求,但是現在有一個新的問題產生了:如果按照題目要求,應該是可以任意的傳遞多個資料,但是以上實際上傳的是一個資料,只不過一個資料使用陣列的形式封裝,那么為了更好的解決這個問題,可以使用JDK1.5的可變引數的方式來解決此問題

Public [static]  [final] 回傳值型別  方法名稱(引數型別…變數){	//雖然方式改變了
    [return [回傳值];]
}

發現現在進行方法引數的定義的時候有了一些變化,而這個時候的引數可以說是陣列形式,

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));
	}
	
 /**
 * 實作任意個數的資料相加操作處理
 * @param data相加操作資料
 * @return	回傳多個資料的相加結果
 */
public static int add(int ... data){
		int sum = 0;
		for (int i = 0; i < data.length; i++) {
			sum += data[i];
		}
		return sum;
	}
}

有了可變引數在日后進行方法呼叫的程序之中,就可以比較直觀的傳遞任意多個引數,但是例外的操作在開發之中不建議使用,最好別用,

2.2 foreach輸出

首先需要解釋的是:foreach并不是新的概念,最早是在NET中提出來的,多為foreach可以理解為增強型的for回圈,下面來回顧一下最早的for回圈:

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));
		
		
	}
	
 /**
 * 實作任意個數的資料相加操作處理
 * @param data相加操作資料
 * @return	回傳多個資料的相加結果
 */
public static int add(int ... data){//接收原始陣列
		int sum = 0;
		for (int i : data) {	//將陣列中的每一個元素設定給x
			sum += i;//這種回圈避免了腳標的問題
		}
		return sum;
	}
}

但是有了foreach之后,那么對于陣列或者是集合的輸出就有了新的支持,語法如下:

for(資料型別  變數 :陣列|集合){
    //操作代碼
}

對于這種for回圈避免了陣列越界的問題,但依然只是要求會使用,能看懂就行,不過個人建議:最好別用,

2.3 靜態匯入

如果說想在想要匯入一個不同包的類的方法,那么肯定使用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.*;//靜態匯入

public class TestMath {
	public static void main(String[] args) {
		System.out.println(add(10,20));
		System.out.println(sub(30,10));
	}
}

這種比較難受的方法,也只是出現在講課之中,本人是絕對不會使用的,你們也可以忘記它,

3、 JDK三大主要特性——泛型

泛型可以幫助我們解決引數轉換的問題

3.1 泛型的引出

下面首先通過一個簡單分析來研究一下泛型出現的主要目的是什么?例如現在要求定義一個表示坐標的操作類(Point)這個類可以表示三種型別的坐標:

? 整數坐標:x=10、y=20;

? 小數坐標:x=10.1、y=20.3;

? 字串資料:x=“東經10度”、y=“西經20度”,

類之中如果想要表示以上的資料,一定需要定義x和y兩個屬性,而且每一個屬性可以接收三種資料型別,那么只能使用Object類來定義會比較合適,這樣會發生如下的幾種轉換關系:

整數:int→自動裝箱為Integer→向上轉型為Object;

小數:double→自動裝箱為Double→向上轉型為Obejct;

字串:字串→向上轉型為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) {
		//第一步:設定資料
		Point p = new Point();
		p.setX(10);
		p.setY(20);
		//第二步:取出資料
		int x = (Integer)p.getX();
		int y = (Integer)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) {
		//第一步:設定資料
		Point p = new Point();
		p.setX(10.1);
		p.setY(20.2);
		//第二步:取出資料
		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) {
		//第一步:設定資料
		Point p = new Point();
		p.setX("東經10");
		p.setY("西經20");
		//第二步:取出資料
		String x = (String)p.getX();
		String y = (String)p.getY();
		System.out.println("x = " + x + ",y = " + y);
	}
}

看起來所有功能都實作了,并根據之前所學的內容,也只能做到這些了,但是本程式還有一系列問題,

本程式解決問題的關鍵就在Object類,所有的型別都可以想Obejct轉換,但是成也是它敗也是它,

public class PointDemo {
	public static void main(String[] args) {
		Point point = new Point();
		//設定引數
		point.setX(10);
		point.setY("北緯");
		//取出引數
		String x = (String) point.getX();
		String y = (String) point.getY();
		System.out.println("x的坐標是:"+x+"y的坐標是:"+y);
	}
}

這個時候程式并沒有任何的語法錯誤,因為數字10 被包裝成了Integer,可以使用Obejct接收,從技術上而言,本操作沒有問題,但是從實際來講,因為沒有統一,多以在取得資料并且執行向下轉型的程序中就會出現如下的錯誤提示資訊:

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)

所以,就可以得出一個結論,以上的程式存在安全隱患,但是并沒有在程式的編譯程序中檢查出來,而現在就可以利用泛型來解決這種問題,

3.2 泛型實作

泛型:類之中操作的屬性或方法的引數型別不在定義的時候宣告,而是在使用的時候動態設定,

package com.demo;
//在定義Point不知道是什么型別,由使用者來進行定義使用
class Point<T> {//T表示引數,一個占位標記
	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) {
		//第一步:設定資料
		Point<String> p = new Point<String>();
		p.setX("東經10");
		p.setY("西經20");
		//第二步:取出資料
		String x = p.getX();//避免了向下轉型
		String y = p.getY();
		System.out.println("x = " + x + ",y = " + y);
	}
}

測驗沒有了向下轉型的操作關系,那么程式就避免了安全性的問題,而且如果設定的型別不統一,在程式編譯的程序之中也是可以很好的解決了,直接會報出語法錯誤,

而且當用戶在使用Point類宣告物件的時候沒有設定泛型,程式在編譯的程序之中,會提示警告資訊,而且為了保證程式不出現錯誤,所有的型別都將使用Obejct進行處理,使用泛型可以很好的解決資料型別的統一問題,

但是在此處需要提醒的是,JDK1.5和JDK1.7在定義泛型的時候是稍微有些區別的,

JDK1.5的時候宣告泛型的操作

Point<String> p= new Point<String>();

以上是JDK1.5的語法,在宣告物件和實體化物件的時候都必須設定好泛型型別,

JDK1.7的時候簡化了

Point<String> p= new Point< >();

? 這個時候實體化物件時泛型的泛型型別就通過宣告時泛型型別來定義了,

3.3 通配符

泛型的而出現的確是可以解決了資料的統一問題以及避免了向下轉型操作,但同事也會帶來新的問題,下面通過一段程式,來觀察一下會產生什么問題?

為了簡化定義一個簡單的泛型

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

但是如果現在定義的泛型型別不是String呢?例如:換成了int(不能是基本資料型別,只能是包裝類)

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

發現這個時候的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());
	}
}

這個時候發現按照之前的方式根本就無法進行方法的多載,方法的多載沒有說為一個類而定義的,因為方法多載的時候觀察的不是泛型型別,而是類的名稱,或者說是資料型別的,所以現在就可以發現,這個給出了泛型類之后,就相當于將一個類又劃分成了幾個小類,

image-20210815130238917

那么現在的問題:方法接收的引數問題又嚴重了,而且比之前使用物件多型性解決問題時出現的麻煩更大了,至少那個時候可以利用多載來接收一個類的所有子類物件,而現在連多載都使用不了,

? 這個時候,有人提出了,干脆在定義方法的時候就別寫泛型型別了,

定義方法的時候不定義泛型型別

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

雖然現在print()方法的引數上出現了警告,但是現在的程式可算是正常了,但是新的問題又來了,問題就在于方法操作中,沒有型別限制了,

public static void print(Message msg){
		msg.setInfo(100);
		System.out.println(msg.getInfo());
}

發現此時在print()方法之中操作的時候,由于沒有設定泛型型別,那么所有型別都統一變為了Object,也就可以修改了,而通過本程式也就發現了,必須找到一種方法,:此方法可以接收任意的泛型型別的設定,并且不能修改,只能輸出,為了解決這樣的問題,可以使用通配符“?”表示,

public static void print(Message<?> msg){
		System.out.println(msg.getInfo());
}

由于“?”出現的情況較多,尤其在學習一些類別庫的時候,所以對于“?”就記住一點,表示任意型別,如果有引數回傳的時候也是這個“?”,當成Object進行理解,

既然現在談到了Obejct,那么現在實際上又有了另外一個問題:對于所有的子類,都是Object子類,那么如果對于之前的程式都使用Object能不能接收?

Message<String> msg = new Message<>();
Message<Object> s = msg;

因為Object的范圍比String的范圍大,

而在通配符“?”上有衍生出了兩個子符號:

  1. 設定泛型的上限:?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);
	}
	//此時使用通配符“?”描述的是它可以接收任何任意資料型別,但是由于不確定型別,無法修改
	public static void print(Message<? super String> s){
			System.out.println(s.getInfo());
	}
}
3.4 泛型介面

在之前的所有定義的泛型之中,都是在類上定義的,而對于介面也是可以進行泛型定義的,而使用泛型定義的介面可以稱為泛型介面,

interface Message<T>{
	public String echo(T msg);
}

而對于泛型介面的實作,在Java中有兩種方式:

方式一:在子類上繼續定義泛型,同時此泛型繼續在介面上使用

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三大主要特性——列舉

在講解列舉之前回顧一個概念:多例設計模式,構造方法私有化(非public),之后在類的內部存在若干個指定的物件,通過一個方法回傳指定物件,

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

基于列舉開發

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類

很明顯,現在可以發現,利用列舉實作多例設計會更加的簡單直白一些,但是在Java之中,列舉并不是一個新的型別,嚴格來講,每一個使用enum定義的類實際上都屬于一個類繼承了Enum父類而已,而java.lang.Enum類定義如下:

public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable

而在Enum類種子紅定義了兩個方法:

  1. 取得列舉的序號:public final int ordinal();
  2. 取得列舉的名稱: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());
	}
}

取得所有顏色資料

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的區別?

enum是一個關鍵字,使用enum定義的列舉類本質上相當于一個類繼承了Enum類而已,

4.3 列舉中定義其它結構

按照之前所理解,列舉就屬于多例設計模式,那么既然是多例設計模式,對于類之中就肯定有多種組成,包括屬性,方法,構造方法,在列舉之中也同樣可以定義以上的內容,不過需要注意的是,列舉類之中定義的構造方法絕對不能是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

方法的覆寫:發生繼承關系之中,子類定義了與父類的方法名稱相同、引數型別以及個數相同的覆寫,被覆寫的方法不能夠擁有比父類更為嚴格的訪問控制權限,

package com.annotation;
class Person{
	//現在是希望進行toString()覆寫,但遺憾的由于你自己的輸入錯誤,導致方法的覆寫錯誤
	//@Override
	public String tostring(){//現在希望可以進行toString()方法的覆寫
		return "一個人";
	}
}
public class Demo1 {
	public static void main(String[] args) {
		System.out.println(new Person().tostring());
	}
}

這個時候不叫覆寫,屬于自己定義一個擴展的方法,最為重要的是,這個問題在程式編譯的根本就無法顯示出來,但是現在為了保證我們的覆寫方法的嚴格,可以使用一個注解(@Override)來檢測:如果該方法確定成的覆寫了

,則不會有我們的語法錯誤,如果進行成功的覆寫,認為語法的錯誤,

package com.annotation;
class Person{
	//現在是希望進行toString()覆寫,但遺憾的由于你自己的輸入錯誤,導致方法的覆寫錯誤
	public String toString(){//現在希望可以進行toString()方法的覆寫
		return "一個人";
	}
}
public class Demo1 {
	public static void main(String[] args) {
		System.out.println(new Person());
	}
}
5.2 宣告過期操作:@Deprecated

對于程式開發而言,往往一些使用的類要進行修改或者是維護,如果說現在一個類之中的某個方法,可能一開始推出的時候正常使用,但是在后面的版本就存在了一些問題,在修改之后不希望人再去使用這些方法,那么肯定不能直接洗掉,因為如果直接洗掉了,那么之前的程式就會出現問題了,所以最好的做法是告訴用戶:這個方法存在了問題,不建議再使用了,這個時候就使用“@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();
	}
}

image-20210815220449698

關于軟體的開發模式;

? 第一階段:會將所有的操作都寫在程式之中,例如:網路程式,連接程式,連接的服務器地址,用戶驗證等;

? 第二階段:程式+組態檔,組態檔和程式相分離,組態檔過多,后期修改非常復雜;

? 第三階段:將組態檔寫回到程式之中,但是和程式進行有效的分離,

6、介面定義加強

image-20210815221420943

造成此種尷尬的局面的核心問題在于,介面只是一個方法的宣告,而沒有具體方法的實作,所以隨著時間的推移,如果出現以上的問題,該介面將無法繼續使用,從JDK1.8為了解決這個問題,專門提供兩種專門的介面,

  1. 可以使用default來定義普通方法,需要通過物件呼叫,
  2. 可以使用static來定義靜態方法,通過介面名就能使用,

定義普通方法

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(){//定義靜態方法
		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();
	}
}

整體來說,介面更像抽象類,但是比抽象類強大在于,介面的子類依然可以實作多繼承的關系,而抽象類繼續保持單繼承,

7、Lambda運算式

最具有代表性的就是haskell.函式式編程和面向物件編程為兩大開發陣營

傳統的面向物件開發

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

使用匿名內部類來實作介面最大好處就是節約了一個檔案,最大的缺點就是看的眼花繚亂,對于此操作有了更簡化的體現,如果采用函式式編程模型,

函式式編程模型

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

如果想要使用函式式編程前提,介面只能寫一個方法,如果撰寫兩個方法,則會出現語法錯誤,可以在介面的開頭加上@FunctionalInterface宣告這是一個函式介面,

實際上對于以上的語法形式:

  • (引數 )->單行陳述句;

image-20210815224619650

這個時候方法本身只包含一行陳述句,那么直接撰寫陳述句即可,如果要是有多行陳述句,則就需要我們使用"{}"

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

如果現在你的運算式里面的內容只是一行進行資料的回傳,那么直接使用陳述句即可,不用寫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));
	}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/294461.html

標籤:java

上一篇:半小時體驗云原生:手把手教你在k8s上部署springboot應用——干貨分享,建議收藏

下一篇:LeetCode 24. 兩兩交換鏈表中的節點 【c++/java詳細題解】

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more