通俗易懂讲

您所在的位置:网站首页 一个括号里面一个问号怎么打 通俗易懂讲

通俗易懂讲

2024-07-14 09:47| 来源: 网络整理| 查看: 265

目录

(一)泛型方法

(二)泛型类

(三)泛型申明

1、泛型申明的作用域

2、申明多个泛型

3、泛型可以在申明时限定使用范围

(四)问号“?”与泛型的关系

1、“?”用于初始化赋值。

2、“?”用于限定值的更新

3、“?”可以独立用于参数范围的限定

4、“?”通配符也可以和泛型配合

(五)泛型数组和泛型接口

力求通俗易懂,便于记忆。

(一)泛型方法

编程中经常会遇到相同的方法,相同的结构,只是变量类型不同。通常可以如下多写几个方法,但是代码量很大,如下例中的getprint():

public class Test { public static String getprint(String s) { return s; } public static Integer getprint(Integer i) { return i; } public static ArrayList getprint(ArrayList l) { return l; } public static void main(String[] args) { System.out.println(getprint("abc")); System.out.println(getprint(123)); ArrayList list = new ArrayList(); list.add("aaa"); list.add("bbb"); System.out.println(getprint(list)); } } /* 运行结果: abc 123 [aaa, bbb] */

既然只是类型不同,那有没有一种“类型变量”呢?

 我们可以用java提供的泛型来实现这种“类型变量”,以达到简化代码的目的。ps:不知道为翻译成泛型,我们可以理解成“广泛的类型”,或者理解成“通用类型”。

像其他变量一样,使用泛型也必须要申明,1、在方法的返回值类型前加,申明泛型T。当然也可以是其他字母,泛型习惯上使用大写的T、V、E等。2、上例中我们把那些变化的类型:String、Integer、 ArrayList用T代替。简化成如下代码:

public class Test { public static T getprint(T s) {return s;} public static void main(String[] args) { System.out.println(getprint("abc")); System.out.println(getprint(123)); ArrayList list=new ArrayList(); list.add("aaa"); list.add("bbb"); System.out.println(getprint(list)); } }

是不是简化很多?这种含有泛型申明的方法我们把他称之为:泛型方法,其中T称之为泛型。

这里需要说明下:getprint(T s)我们例子中传入了三个参数:"abc"、123、list,但并没有指定类型。是的,java自动判断了传入参数的类型,当传入"abc"时,java会判断传入了String类型,并自动将T替换成String,变成了一个String类型的方法,再传入参数:

public static String getprint(String s) { return s; }

结论:泛型是一种变量

           1、泛型方法:像其他变量一样使用泛型必须申明一个或多个泛型,即在方法的返回类型前加,用以申明泛型T,表示该方法可以使用泛型T。

           2、泛型方法在传入参数时就会确定泛型T的类型,并将T替换成对应类型。

           3、泛型T可以为其他字母,但通常习惯用单个大写字母T、V、E等。

(二)泛型类

既然方法可以用泛型(通用类型),那么类呢?当然是可以的,先看代码:

public class Study { public static void main(String[] args) { Test01 test01 = new Test01("abc"); System.out.println(test01.getKey()); // Test02 test02 = new Test02(123); System.out.println(test02.getKey()); // Test03 test03 = new Test03(new ArrayList(Arrays.asList("aaa", "bbb"))); System.out.println(test03.getKey()); } } class Test01 { private String key; public Test01(String key) {this.key = key;} public String getKey() {return key;} public void setKey(String key) {this.key = key;} } class Test02 { private Integer key; public Test02(Integer key) {this.key = key;} public Integer getKey() {return key;} public void setKey(Integer key) {this.key = key;} } class Test03 { private ArrayList key; public Test03(ArrayList key) {this.key = key;} public ArrayList getKey() {return key;} public void setKey(ArrayList key) {this.key = key;} } /* 运行结果: abc 123 [aaa, bbb] */

Test01、Test02、Test03三个类有相同的方法,相同的结构,只是变量类型不同。

将上述三个类简化成一个泛型类,1、申明一个泛型,在类名后加。2、把上述三个类不同的类型:String、Integer、 ArrayList替换成T。简化得到如下代码:

public class Study { public static void main(String[] args) { Test test01=new Test("abc"); System.out.println(test01.getKey()); // Test test02=new Test(123); System.out.println(test02.getKey()); // Test test03=new Test(new ArrayList(Arrays.asList("aaa", "bbb"))); System.out.println(test03.getKey()); } } class Test { private T key; public Test(T key) {this.key = key;} public T getKey() {return key;} public void setKey(T key) {this.key = key;} }

需要说明下,泛型类跟普通类比较,泛型类需要在申明时类名后用尖括号指定类型:

普通类:Test test=new Test();

泛型类:Test test =new Test();//等号后面那个尖括号里的String可以不要

尖括号指定String类型后,java系统会将该泛型类中的T替换成了String,自动生成了普通类。

class Test { private String key; public Test(String key) {this.key = key;} public String getKey() {return key;} public void setKey(String key) {this.key = key;} }

如果泛型类申明时不指定类型,类型自动默认为Object。

结论:

           1、申明泛型:泛型类的类名后面一定要加以申明泛型T,表示该类可以使用泛型T了。

           2、申明泛型类:需要在申明时类名后用尖括号指定类型:java在申明后泛型类会将T替换成指定类型生成普通类。Test test =new Test();

           3、尖括号里的变量类型不能是基础变量类型:byte、short、int、long、float、double、char、boolean,必须用对应的:Byte、Short、Integer、Long、Float、Double、Character、Boolean。

           4、泛型T可以为其他字母,但通常习惯用大写字母T、V、E等。

(三)泛型申明 类似于变量申明,在类名后面或者方法返回类型前面加,即表示申明了一个泛型T。该泛型T可以分别用于类或者方法中,在被调用前T自动替换成对应的类型。也称为"泛型标识符"。最简单的泛型方法:public static void p(){}//申明了泛型T但未使用 1、泛型申明的作用域 public class Stdudy { /* * 方法前无,泛型类中的方法,其中的T类型与泛型类的T类型一致。 */ public T gogo(T t) {return t;} /* * 方法前有,泛型方法,其中的T类型是独立的,不受泛型类的T类型约束 */ public T go(T t) { return t; } public static void main(String[] args) { String s = "abc"; new Stdudy().go(s); } }

上例中出现两次,也就是泛型T被申明了两次,第一次是类名后,第二次是在方法go()前。

泛型其实就是一种变量,类的泛型T只能影响除go()方法外的所有T,go()方法的T相当于局部变量独立使用,不受类泛型T的影响。

静态方法只能使用泛型方法,泛型类无法影响静态方法中的泛型T。

2、申明多个泛型

泛型可以申明多个,需在泛型标识符里申明。并在方法或类中应用。如:

public class TestMethod { public static void print(T t,R r){ System.out.println(""+t+r); } public static void main(String[] args) { print("abc",123); } } public class TestMethod { public void print(T t,R r){ System.out.println(""+t+r); } public static void main(String[] args) { new TestMethod().print("abc",123); } } 3、泛型可以在申明时限定使用范围

extends:表示类型上界。例:A extends B,表示类型必须是B或B的子类

super:表示类型下界。例:A super B,表示类型必须是B或B的父类

&:接口

public static I getI(I i){ return i; } (四)问号“?”与泛型的关系 “?”是泛型通配符。但他不是泛型。好比是张三的苹果,不能说苹果就是张三。“?”通常是独立使用,与泛型无关,也可以与泛型配合使用。“?”不是泛型,因此不能用于泛型申明。泛型实际是一种类型占位符,在调用泛型方法或者泛型类之前就确定了类型,调用前先将泛型替换成了对应的类型再调用。因此泛型实质是确定的类型。ps:通俗说法便于理解别较真“?”是不确定的类型,他表达的是一个类型范围。因此“?”定义的list,由于类型范围的问题,插入会校验时会报错。例如:List list=new ArrayList();(后面会详细讲原理。) 1、“?”用于初始化赋值。 初始化赋值时,会校验初始化值的类型是否在的范围内,的上限值是Object,下限值是无穷小的子类,因此任何类型都在其范围内。 classType = Class.forName("java.lang.String"); List listString = new ArrayList(); List listString中下限是无穷小子类,也就是没下限。因此很尴尬,listString无法插入除null以外的任何值。同理List listString = new ArrayList(); //除null值外,都不能插入,可以读取 List


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3