泛型:java
參數化數據類型ide
做用於
類,方法,構造器,接口函數
泛型類:this
在聲明類的後面加上類型參數對象
好處語法排序
類名<類型參數>
類型參數能夠是一個也能夠是多個,多個用逗號分隔繼承
用一個大寫字母表示,通常用 T-type E—element K—key V—value接口
原生類型:ci
類型後沒有 指定具體的類型參數,這樣的類型element
叫 原生類型。
泛型的通配符
?是無界通配符,能夠匹配任意的引用類型
? extends 上限類型 及其上限類型的子類型
super 能夠匹配下限類和下限類的父類
注意
類型參數能夠指定上限(上界),
1.可是隻能指定上界
2.還能夠指定多個上限
3.上限能夠是類也能夠是接口
4.上限既有類又有接口,要先繼承類,後實現接口;類在前,接口在後
類型參數和通配符的區別
1.類型參數 只能指定上限,通配符能夠指定上限和下限
2.類型參數能夠指定多個上限,通配符只能指定一個
3.類型參數能夠做爲一個類型,通配符不能表示爲一種類型
問題,String是Object的子類,那麼Point 是不是Point的子類型
答:不是,參數化類型不能繼承
//用通配符解決
public void show(Point<String> ps,Point<? extends Object> po){
po = ps;
}
1
2
3
4
5
問題:會生成幾個泛型類
一個。泛型只是起到在編譯時期進行類型檢查的做用,並不會生成多個字節碼文件
//驗證
Point3<Integer> p1 = new Point3();
System.out.println(p1.getClass());
Point3<String> p2 = new Point3<>();
System.out.println(p2.getClass());
//運行結果:
class day21.Point3
class day21.Point3
泛型構造
package day21;
class Point4<T>{
private T x;
private T y;
//泛型構造器
<E>Point4(E e){
System.out.println(e);
}
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 Ex4 {
public static void main(String[] args) {
//類型推斷:根據串的參數的類型肯定E是String
Point4<Integer> p4 = new Point4<Integer>("Hello");
Point4<Integer> p6 = new Point4<>("hello");
//顯示指定構造器是String類型,此時不能用菱形語法
Point4<Integer> p5 = new <String>Point4<Integer>("Hello");
}
}泛型方法
package day21;
//普通類
class Point5{
//泛型方法
public <T> void f(T t){
System.out.println(t);
}
//<一>
//public <T extends Number> T ff (T t){
//<二>
public <T extends Number> T ff (T t){
//自動推斷
f("hello");
//若是顯示指定的化,要用對象去調用:this.<String>f("abc");this.<String>f("abc");都是指定了對象
this.<String>f("abc");
return t;
}
}
public class Ex5 {
public static void main(String[] args) {
Point5 p5 = new Point5();
//類型推斷:根據參數的類型推斷
p5.f("Hello");
p5.f(11);
//<一>
//顯示指定類型參數
//p5.<String>f("abc");
//<二>
p5.<Double>f(11.0);
}
}
類型擦除
1.參數化類型擦除後爲原生類型
point -> point
2.類型參數:使用上界替換
(1)無界類型參數
Point ——> Object
會用Object替換
(2)指定了一個上限的,用此上限類型來替換
Point ——> Base
(3)指定了多個上限的,用第一個上限替換
Point
重寫方法
package day21;
interface IA1{
}
interface IB1{
}
class Base1 {
public void f(Point6<String> p) throws Exception {}
}
class Sub1 extends Base1 {
//重寫了
@Override
public void f(Point6<String> p) throws Exception{
// TODO Auto-generated method stub
super.f(p);
}
}
class Point6<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 Ex6 {
public void f(Point6<String> p){}//Point6
public <T> void f(T p){};//Object
public <T extends Base1> void f(T p){} //Base1
public <T extends IA1 & IB1> void f(T p){} //IA1
public static void main(String[] args) {
}
}
父類參數擦除後和子類相同
異常範圍不能比父類大
泛型接口
package day21;
//泛型接口
interface Info <T>{
void af(T t);
}
//實現類一:實現接口的時候就指定好用什麼類型來替換
class InfoImpl1 implements Info<String>{
@Override
public void af(String t) {
// TODO Auto-generated method stub
}
}
//實現類二:肯定不了類型,等應用再定義:InfoImpl2<String> info = new InfoImpl2<String> ();
class InfoImpl2<T> implements Info<T>{
@Override
public void af(T t) {
// TODO Auto-generated method stub
}
}
public class Ex7 {
public static void main(String[] args) {
InfoImpl2<String> info = new InfoImpl2<String> ();
}
}
比較器 TestCompare
天然排序:按照 Comparable接口的方法CompareTo排序
問題:不想按照現有排序方法進行排序,應該怎麼解決
實現Comparator 函數式接口
Comparator Exercise4 和 Comparable的區別 Exercise3
1.Comparable是默認的天然排序方式,Comparator 是咱們指定的一種排序方式
2.Comparable的比較代碼寫在要比較對象的類型的內部,Comparator寫在比較類型代碼的外部
3.Comparable只能指定一種 默認排序方式,Comparator能夠定義多種排序方式
枚舉
底層就是class類
已經繼承了一個類Enum,不能再繼承其餘的類
對於一個非抽象的枚舉類型,默認是final
構造器是private的
不能建立對象,在枚舉代碼的第一行處
全部的枚舉對象都是 public static final的
當枚舉的類中定義了抽象方法,那麼每一個對象的匿名內部類方式都必須實現這個抽象方法,而且這個枚舉類爲abstract的
語法:
enum Color{
枚舉成員;
方法();
構造();
}
1
2
3
4
5
實例代碼
package day21;
import java.util.Scanner;
interface InfoNew{
void af();//抽象方法
}
//能夠實現接口
enum Color implements InfoNew{
//在這裏調用構造器
RED(1,"紅色"){
@Override
public void af() {
System.out.println("紅色的實現接口");
}
@Override
void f() {
System.out.println("紅色的實現抽象類");
}
},GREEN(2,"綠色"){
@Override
public void af() {
System.out.println("綠色的實現接口");
}
@Override
void f() {
System.out.println("綠色的實現抽象類");
}
}, BLUE(3,"藍色"){
@Override
public void af() {
System.out.println("藍色的實現接口");
}
@Override
void f() {
System.out.println("綠色的實現抽象類");
}
};
//成員變量
private int no;
private String name;
//構造器 是private的,在這裏寫不必
private Color(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//自定義方法
public void show(){
System.out.println("show");
}
//重寫
@Override
public String toString() {
return no + name;
}
//定義抽象方法
abstract void f();
}
public class Ex8 {
public static void main(String[] args) {
//重寫了Stringto
System.out.println(Color.RED);
//定義了構造器
System.out.println(Color.RED.getName() +","+ Color.RED.getNo());
System.out.println(Color.BLUE.getName() +","+ Color.BLUE.getNo());
System.out.println(Color.GREEN.getName() +","+ Color.GREEN.getNo());
//定義成員變量
/* Color.RED.no = 11;
Color.RED.name = "紅色";
System.out.println(Color.RED.name);
System.out.println(Color.RED.no);
*/
//私有成員變量
Color.RED.setNo(22);
Color.RED.setName("紅色");
System.out.println(Color.RED.getName() +"," +Color.RED.getNo());
//每個枚舉成員均可以調用自定義方法
Color.BLUE.show();
//-----------------------------------
/* System.out.println(Color.RED);
System.out.println(Color.GREEN);
System.out.println(Color.BLUE);
//遍歷
for (Color c : Color.values()){
System.out.println(c.name());
//得到枚舉類型的編號
System.out.println(c.ordinal());
}
//-----------Switch------------------
Scanner input = new Scanner(System.in);
System.out.println("輸入顏色");
String str = input.next();
//字符串轉換爲枚舉Color類型
Color c = Color.valueOf(str);
switch (c){
case RED:
System.out.println("是紅色");
break;
case GREEN:
System.out.println("是綠色");
break;
case BLUE:
System.out.println("是藍色");
break;
}*/
}
}