- 浏览: 25855 次
- 性别:
- 来自: 成都
文章分类
最新评论
1. 介绍
下面是那种典型用法:
List myIntList = new ArrayList();// 1
myIntList.add(new Integer(0));// 2
Integer x = (Integer) myIntList.iterator().next();// 3
第 3 行的类型转换有些烦人。通常情况下,程序员知道一个特定的 list
里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编
译器只能保证 iterator 返回的是 Object 类型。为了保证对 Integer 类型变量
赋值的类型安全,必须进行类型转换。
当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误
(run time error) ,因为程序员可能会犯错。
程序员如何才能明确表示他们的意图,把一个 list(集合) 中的内容限制
为一个特定的数据类型呢?这就是 generics 背后的核心思想。这是上面程
序片断的一个泛型版本:
List<Integer> myIntList = new ArrayList<Integer>(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = myIntList.iterator().next(); // 3
注意变量 myIntList 的类型声明。它指定这不是一个任意的 List ,而是
一个 Integer 的 List ,写作:List<Integer>。我们说 List 是一个带一个类型
参数的泛型接口(a generic interface that takes a type parameter) ,本
例中,类型参数是 Integer。我们在创建这个 List 对象的时候也指定了一个类型参数。
另一个需要注意的是第 3 行没了类型转换。
现在,你可能认为我们已经成功地去掉了程序里的混乱。我们用第 1
行的类型参数取代了第 3 行的类型转换。然而,这里还有个很大的不同。
编译器现在能够在编译时检查程序的正确性。当我们说 myIntList 被声明为
List<Integer>类型,这告诉我们无论何时何地使用 myIntList 变量,编译器
保证其中的元素的正确的类型。
实际结果是,这可以增加可读性和稳定性(robustness) ,尤其在大型的程序中。
2. 定义简单的泛型
下面是从java.util 包中的 List 接口和 Iterator 接口的定义中摘录的片断:
public interface List<E> {
void add(E x);
Iterator<E> iterator(); }
public interface Iterator<E> {
E next();
boolean hasNext();
}
这些都应该是很熟悉的,除了尖括号中的部分,那是接口 List 和 Iterat
or 中的形式类型参数的声明(the declarations of the formal type param
eters of the interfaces List and Iterator)。
类型参数在整个类的声明中可用,几乎是所有可以使用其他普通类型的
地方
在介绍那一节我们看到了对泛型类型声明 List (the generic type decl
aration List) 的调用,如 List<Integer>。在这个调用中(通常称作一个参数
化类型 a parameterized type) ,所有出现的形式类型参数(formal type pa
rameter,这里是 E)都被替换成实体类型参数(actual type argument)(这里是Integer)。
你可能想象,List<Integer>代表一个 E 被全部替换成 Integer 的版本 :
public interface IntegerList {
void add(Integer x)
Iterator<Integer> iterator();
}
类型参数就跟在方法或构造函数中普通的参数一样。就像一个方法有形
式参数(formal value parameters)来描述它操作的参数的种类一样,一个
泛型声明也有形式类型参数(formal type parameters)。当一个方法被调用,
实参(actual arguments)替换形参,方法体被执行。当一个泛型声明被调用,
实际类型参数(actual type arguments)取代形式类型参数。
一个命名的习惯:推荐用简练的名字作为形式类型参数的名字(如果可能,单个符)最好避免小写字母
3. 泛型和子类继承
让我们测试一下我们对泛型的理解。下面的代码片断合法么?
List<String> ls = new ArrayList<String>(); //1
List<Object> lo = ls; //2
第 1 行当然合法,但是这个问题的狡猾之处在于第 2 行。
这产生一个问题:
一个 String 的 List 是一个 Object 的 List 么?大多数人的直觉是回答:
好,在看下面的几行:
lo.add(new Object()); // 3
String s = ls.get(0); // 4: 试图把 Object 赋值给 String
这里,我们使用 lo 指向 ls。我们通过 lo 来访问 ls,一个 String 的 list。
我们可以插入任意对象进去。结果是 ls 中保存的不再是 String。当我们试
图从中取出元素的时候,会得到意外的结果。
java 编译器当然会阻止这种情况的发生。第 2 行会导致一个编译错误。
总之,如果 Foo 是 Bar 的一个子类型(子类或者子接口) ,而G 是某种
泛型声明,那么 G<Foo>是 G<Bar>的子类型并不成立!!
为了处理这种情况,考虑一些更灵活的泛型类型很有用。到现在为止我
们看到的规则限制比较大。
4. 通配符(Wildcards)
考虑写一个例程来打印一个集合(Collection)中的所有元素。下面是在老
的语言中你可能写的代码:
void printCollection(Collection c) {
Iterator i = c.iterator();
for (int k = 0; k < c.size(); k++) {
System.out.println(i.next());
}
}
下面是一个使用泛型的幼稚的尝试(使用了新的循环语法):
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e);
}
}
问题是新版本的用处比老版本小多了。老版本的代码可以使用任何类型
的 Collection 作为参数,而新版本则只能使用 Collection<Object> ,我们刚
才阐述了,它不是所有类型的 collections 的父类。
那么什么是各种 collections 的父类呢 ?它写作: Collection<?>(发音
为:"collection of unknown") ,就是,一个集合,它的元素类型可以匹配任
何类型。显然,它被称为通配符。我们可以写:
void printCollection(Collection<?> c) {
for (Object e : c) {
System.out.println(e);
}
}
现在,我们可以使用任何类型的 collection 来调用它。注意,我们仍然
可以读取 c 中的元素,其类型是 Object。这永远是安全的,因为不管 colle
ction 的真实类型是什么,它包含的都是 Object。
但是将任意元素加入到其中不是类型安全的 :
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
因为我们不知道 c 的元素类型,我们不能向其中添加对象。
add 方法有类型参数 E 作为集合的元素类型。我们传给 add 的任何参
数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我
们无法传任何东西进去。唯一的例外是 null ,它是所有类型的成员。
另一方面,我们可以调用 get()方法并使用其返回值。返回值是一个未
知的类型,但是我们知道,它总是一个 Object
4.1. 有限制的通配符(Bounded Wildcards)
考虑一个简单的画图程序,它可以用来画各种形状,比如矩形和圆形。
为了在程序中表示这些形状,你可以定义下面的类继承结构:
public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
private int x, y, radius;
public void draw(Canvas c) { // ...
}
}
public class Rectangle extends Shape {
private int x, y, width, height;
public void draw(Canvas c) {
// ...
}
}
这些类可以在一个画布(Canvas)上被画出来:
public class Canvas {
public void draw(Shape s) {
s.draw(this);
}
}
所有的图形通常都有很多个形状。假定它们用一个 list 来表示,Canvas 里有一个方法来画出所有的形状会比较方便:
public void drawAll(List<Shape> shapes) {
for (Shape s : shapes) {
s.draw(this);
}
}
现在,类型规则导致 drawAll()只能使用 Shape 的 list 来调用。它不能,
比如说对 List<Circle>来调用。这很不幸,因为这个方法所作的只是从这个
list 读取 shape ,因此它应该也能对List<Circle>调用。我们真正要的是这 个方法能够接受一个任意种类的 Shape:
public void drawAll(List<? extends Shape> shapes) { //..}
这里有一处很小但是很重要的不同:我们把类型 List<Shape> 替换成了 List<? extends Shape>。现在 drawAll()可以接受任何 Shape 的子类的 List ,所以我们可以对List<Circle>进行调用。
List<? extends Shape>是有限制通配符的一个例子。这里?代表一个未知的类型 ,就像我们前面看到的通配符一样。但是,在这里,我们知道
这个未知的类型实际上是 Shape 的一个子类。我们说 Shape 是这个通配符的上限(upper bound)。
像平常一样,要得到使用通配符的灵活性有些代价。这个代价是,现在
向 shapes 中写入是非法的。比如下面的代码是不允许的:
public void addRectangle(List<? extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
你应该能够指出为什么上面的代码是不允许的。因为 shapes.add 的第
二个参数类型是 ? extends Shape —— 一个 Shape 未知的子类。因此我
们不知道这个类型是什么,我们不知道它是不是 Rectangle 的父类;它可 能是也可能不是一个父类,所以这里传递一个 Rectangle 不安全。
5. 泛型方法
考虑写一个方法,它用一个 Object 的数组和一个 collection 作为参数,
完成把数组中所有 object 放入 collection 中的功能。
下面是第一次尝试:
static void fromArrayToCollection(Object[] a, Collection<?> c) {
for (Object o : a) {
c.add(o); // 编译期错误
}
}
现在,你应该能够学会避免初学者试图使用 Collection<Object>作为集
合参数类型的错误了。或许你已经意识到使用 Collection<?>也不能工作。
回忆一下,你不能把对象放进一个未知类型的集合中去。解决这个问题的办法是使用 generic methods。就像类型声明,方法的
声明也可以被泛型化——就是说,带有一个或者多个类型参数。
static <T> void fromArrayToCollection(T[] a, Collection<T> c){ for (T o : a) {
c.add(o); // correct
}
}
我们可以使用任意集合来调用这个方法,只要其元素的类型是数组的元素类型的父类。
Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T 指 Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, co);// T inferred to be Object
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
----------------------- Page 13-----------------------
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error
注意,我们并没有传送真实类型参数(actual type argument)给一个泛
型方法。编译器根据实参为我们推断类型参数的值。它通常推断出能使调
用类型正确的最明确的类型参数。
下面是那种典型用法:
List myIntList = new ArrayList();// 1
myIntList.add(new Integer(0));// 2
Integer x = (Integer) myIntList.iterator().next();// 3
第 3 行的类型转换有些烦人。通常情况下,程序员知道一个特定的 list
里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编
译器只能保证 iterator 返回的是 Object 类型。为了保证对 Integer 类型变量
赋值的类型安全,必须进行类型转换。
当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误
(run time error) ,因为程序员可能会犯错。
程序员如何才能明确表示他们的意图,把一个 list(集合) 中的内容限制
为一个特定的数据类型呢?这就是 generics 背后的核心思想。这是上面程
序片断的一个泛型版本:
List<Integer> myIntList = new ArrayList<Integer>(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = myIntList.iterator().next(); // 3
注意变量 myIntList 的类型声明。它指定这不是一个任意的 List ,而是
一个 Integer 的 List ,写作:List<Integer>。我们说 List 是一个带一个类型
参数的泛型接口(a generic interface that takes a type parameter) ,本
例中,类型参数是 Integer。我们在创建这个 List 对象的时候也指定了一个类型参数。
另一个需要注意的是第 3 行没了类型转换。
现在,你可能认为我们已经成功地去掉了程序里的混乱。我们用第 1
行的类型参数取代了第 3 行的类型转换。然而,这里还有个很大的不同。
编译器现在能够在编译时检查程序的正确性。当我们说 myIntList 被声明为
List<Integer>类型,这告诉我们无论何时何地使用 myIntList 变量,编译器
保证其中的元素的正确的类型。
实际结果是,这可以增加可读性和稳定性(robustness) ,尤其在大型的程序中。
2. 定义简单的泛型
下面是从java.util 包中的 List 接口和 Iterator 接口的定义中摘录的片断:
public interface List<E> {
void add(E x);
Iterator<E> iterator(); }
public interface Iterator<E> {
E next();
boolean hasNext();
}
这些都应该是很熟悉的,除了尖括号中的部分,那是接口 List 和 Iterat
or 中的形式类型参数的声明(the declarations of the formal type param
eters of the interfaces List and Iterator)。
类型参数在整个类的声明中可用,几乎是所有可以使用其他普通类型的
地方
在介绍那一节我们看到了对泛型类型声明 List (the generic type decl
aration List) 的调用,如 List<Integer>。在这个调用中(通常称作一个参数
化类型 a parameterized type) ,所有出现的形式类型参数(formal type pa
rameter,这里是 E)都被替换成实体类型参数(actual type argument)(这里是Integer)。
你可能想象,List<Integer>代表一个 E 被全部替换成 Integer 的版本 :
public interface IntegerList {
void add(Integer x)
Iterator<Integer> iterator();
}
类型参数就跟在方法或构造函数中普通的参数一样。就像一个方法有形
式参数(formal value parameters)来描述它操作的参数的种类一样,一个
泛型声明也有形式类型参数(formal type parameters)。当一个方法被调用,
实参(actual arguments)替换形参,方法体被执行。当一个泛型声明被调用,
实际类型参数(actual type arguments)取代形式类型参数。
一个命名的习惯:推荐用简练的名字作为形式类型参数的名字(如果可能,单个符)最好避免小写字母
3. 泛型和子类继承
让我们测试一下我们对泛型的理解。下面的代码片断合法么?
List<String> ls = new ArrayList<String>(); //1
List<Object> lo = ls; //2
第 1 行当然合法,但是这个问题的狡猾之处在于第 2 行。
这产生一个问题:
一个 String 的 List 是一个 Object 的 List 么?大多数人的直觉是回答:
好,在看下面的几行:
lo.add(new Object()); // 3
String s = ls.get(0); // 4: 试图把 Object 赋值给 String
这里,我们使用 lo 指向 ls。我们通过 lo 来访问 ls,一个 String 的 list。
我们可以插入任意对象进去。结果是 ls 中保存的不再是 String。当我们试
图从中取出元素的时候,会得到意外的结果。
java 编译器当然会阻止这种情况的发生。第 2 行会导致一个编译错误。
总之,如果 Foo 是 Bar 的一个子类型(子类或者子接口) ,而G 是某种
泛型声明,那么 G<Foo>是 G<Bar>的子类型并不成立!!
为了处理这种情况,考虑一些更灵活的泛型类型很有用。到现在为止我
们看到的规则限制比较大。
4. 通配符(Wildcards)
考虑写一个例程来打印一个集合(Collection)中的所有元素。下面是在老
的语言中你可能写的代码:
void printCollection(Collection c) {
Iterator i = c.iterator();
for (int k = 0; k < c.size(); k++) {
System.out.println(i.next());
}
}
下面是一个使用泛型的幼稚的尝试(使用了新的循环语法):
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e);
}
}
问题是新版本的用处比老版本小多了。老版本的代码可以使用任何类型
的 Collection 作为参数,而新版本则只能使用 Collection<Object> ,我们刚
才阐述了,它不是所有类型的 collections 的父类。
那么什么是各种 collections 的父类呢 ?它写作: Collection<?>(发音
为:"collection of unknown") ,就是,一个集合,它的元素类型可以匹配任
何类型。显然,它被称为通配符。我们可以写:
void printCollection(Collection<?> c) {
for (Object e : c) {
System.out.println(e);
}
}
现在,我们可以使用任何类型的 collection 来调用它。注意,我们仍然
可以读取 c 中的元素,其类型是 Object。这永远是安全的,因为不管 colle
ction 的真实类型是什么,它包含的都是 Object。
但是将任意元素加入到其中不是类型安全的 :
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
因为我们不知道 c 的元素类型,我们不能向其中添加对象。
add 方法有类型参数 E 作为集合的元素类型。我们传给 add 的任何参
数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我
们无法传任何东西进去。唯一的例外是 null ,它是所有类型的成员。
另一方面,我们可以调用 get()方法并使用其返回值。返回值是一个未
知的类型,但是我们知道,它总是一个 Object
4.1. 有限制的通配符(Bounded Wildcards)
考虑一个简单的画图程序,它可以用来画各种形状,比如矩形和圆形。
为了在程序中表示这些形状,你可以定义下面的类继承结构:
public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
private int x, y, radius;
public void draw(Canvas c) { // ...
}
}
public class Rectangle extends Shape {
private int x, y, width, height;
public void draw(Canvas c) {
// ...
}
}
这些类可以在一个画布(Canvas)上被画出来:
public class Canvas {
public void draw(Shape s) {
s.draw(this);
}
}
所有的图形通常都有很多个形状。假定它们用一个 list 来表示,Canvas 里有一个方法来画出所有的形状会比较方便:
public void drawAll(List<Shape> shapes) {
for (Shape s : shapes) {
s.draw(this);
}
}
现在,类型规则导致 drawAll()只能使用 Shape 的 list 来调用。它不能,
比如说对 List<Circle>来调用。这很不幸,因为这个方法所作的只是从这个
list 读取 shape ,因此它应该也能对List<Circle>调用。我们真正要的是这 个方法能够接受一个任意种类的 Shape:
public void drawAll(List<? extends Shape> shapes) { //..}
这里有一处很小但是很重要的不同:我们把类型 List<Shape> 替换成了 List<? extends Shape>。现在 drawAll()可以接受任何 Shape 的子类的 List ,所以我们可以对List<Circle>进行调用。
List<? extends Shape>是有限制通配符的一个例子。这里?代表一个未知的类型 ,就像我们前面看到的通配符一样。但是,在这里,我们知道
这个未知的类型实际上是 Shape 的一个子类。我们说 Shape 是这个通配符的上限(upper bound)。
像平常一样,要得到使用通配符的灵活性有些代价。这个代价是,现在
向 shapes 中写入是非法的。比如下面的代码是不允许的:
public void addRectangle(List<? extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
你应该能够指出为什么上面的代码是不允许的。因为 shapes.add 的第
二个参数类型是 ? extends Shape —— 一个 Shape 未知的子类。因此我
们不知道这个类型是什么,我们不知道它是不是 Rectangle 的父类;它可 能是也可能不是一个父类,所以这里传递一个 Rectangle 不安全。
5. 泛型方法
考虑写一个方法,它用一个 Object 的数组和一个 collection 作为参数,
完成把数组中所有 object 放入 collection 中的功能。
下面是第一次尝试:
static void fromArrayToCollection(Object[] a, Collection<?> c) {
for (Object o : a) {
c.add(o); // 编译期错误
}
}
现在,你应该能够学会避免初学者试图使用 Collection<Object>作为集
合参数类型的错误了。或许你已经意识到使用 Collection<?>也不能工作。
回忆一下,你不能把对象放进一个未知类型的集合中去。解决这个问题的办法是使用 generic methods。就像类型声明,方法的
声明也可以被泛型化——就是说,带有一个或者多个类型参数。
static <T> void fromArrayToCollection(T[] a, Collection<T> c){ for (T o : a) {
c.add(o); // correct
}
}
我们可以使用任意集合来调用这个方法,只要其元素的类型是数组的元素类型的父类。
Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T 指 Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, co);// T inferred to be Object
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
----------------------- Page 13-----------------------
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error
注意,我们并没有传送真实类型参数(actual type argument)给一个泛
型方法。编译器根据实参为我们推断类型参数的值。它通常推断出能使调
用类型正确的最明确的类型参数。
发表评论
-
java复制文件高效处理方式
2014-12-18 21:44 13191.实现输出读取文件内容的示列(不推荐使用低效): @T ... -
java中反射:反射的应用--取得类的结构(三)
2014-10-23 14:39 486通过反射的到一个类的完整结构,那么这就要使用到 java.l ... -
java中反射:Class类的使用(二)
2014-10-23 14:33 422通过无参构造实例化对象: 如果想要通过Class类本身实例化 ... -
java中反射:认识Class类(一)
2014-10-21 11:33 498认识Class类: 在正常 ... -
java 批量测试访问谷歌IP
2014-10-21 11:22 483导入jar:log4j-1.2.17.jar,slf4j-ap ... -
java中的Annotation(注解)
2014-10-11 11:42 408Annotation(注释) 概述 从 JDK 5.0 开始, ... -
java 乱码转码类
2014-10-10 21:15 451import java.io.UnsupportedEncod ... -
java中的面向对象
2014-10-09 21:24 454理解面向对象的概念 面向过程 在一个结构体中定义窗 ... -
Java异常
2014-10-09 20:51 295任何一种程序设计语言设计的程序在运行时都有可能出现错误,例如除 ... -
java中3种注释
2014-10-09 08:49 6741、单行注释:在注释内容前加双斜线(//),java编译器会忽 ... -
java中length与length(),size()区别
2014-10-08 17:11 10531、length:在数组操作中,使用length取得数组的长度 ... -
java 多线程有几种现实方式
2014-10-08 16:55 561(1)继承Thread类,重写run函数 创建: cl ... -
java中string与int类型互相转换
2014-10-08 16:51 4231如何将字串 String 转换成整数 int? ... -
java中i++与++i的区别
2014-10-08 16:42 351i++是在一个先使用后加1,即先使用i的值,后让i+1 ++ ... -
Java中16种主流数据库的jdbc连接字符串
2014-10-08 16:39 3751. Microsoft SQLServer(http://w ... -
字符串转换成整数 “456”转换456
2013-06-06 17:11 441http://blog.csdn.net/u010905938 ...
相关推荐
在泛型中,如果尝试向泛型容器添加不匹配的类型,编译器会报错。然而,通过反射或构造旧版本API的方式,仍然可能存在创建“野指针”(即不匹配类型的引用)的风险,这被称为类型擦除的副作用。 9. 有限的多态性 ...
### Java中泛型上下界问题基本问题的介绍 在Java编程语言中,泛型是一种非常重要的特性,它允许程序员编写类型安全的通用代码。通过使用泛型,可以在多个不同的类中重用相同的代码结构,同时确保类型安全性。然而,...
Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。
2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip...
Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战...
Java泛型是Java编程语言中的一个强大特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。这使得代码更加安全、可读性更强,并且能够减少类型转换的必要。在“java泛型的内部原理及更深应用”这个...
Java中的泛型是一种强大的工具,它允许程序员在编写代码时定义类型参数,从而提供更强的类型安全性、减少类型转换,并提高代码的可重用性。泛型是在Java SE 1.5版本中引入的,其本质是参数化类型,这意味着在类、...
Java 中泛型总结 Java 中泛型总结是指在 Java 语言中使用泛型(generics)来实现编译时类型安全检测机制,避免向下转型的隐患。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。在 Java 中,...
在编程世界中,C#和Java都是广泛应用的高级编程语言,它们都支持泛型这一强大的特性,以提高代码的类型安全性和重用性。本文将深入探讨C#和Java在泛型实现上的异同,帮助开发者更好地理解和利用这两种语言的泛型功能...
2. **通配符**:泛型中使用通配符可以增加类型参数的灵活性。例如,`?`表示任何类型,`? extends Number`则限制为Number或其子类。这在处理多种类型的集合时非常有用,如方法参数的定义。 3. **类型擦除**:由于...
感谢所有为Java泛型做出贡献的人们,包括设计者、实现者以及提供反馈和支持的社区成员。泛型是Java语言的一个重要特性,极大地提高了代码的质量和可维护性。 以上就是基于给定文件信息对Java 1.5泛型指南的主要知识...
Java 中泛型通配符的使用方法示例主要介绍了 Java 中泛型通配符的使用方法,结合实例形式分析了 Java 中泛型通配符的功能、语法及在泛型类创建泛型对象中的使用方法。以下是 Java 中泛型通配符的使用方法示例的知识...
综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
Java反射和泛型是两种强大的编程特性,它们在开发中有着广泛的应用,特别是在数据库操作的动态化场景下。本文将详细介绍如何结合这两种技术实现在Java中对MySQL、SQL Server或Oracle数据库进行动态的增删改查操作。 ...
泛型是Java编程语言中的一个重要特性,它引入于JDK 5.0,极大地提高了代码的类型安全性和可读性。泛型允许我们在类、接口和方法中使用类型参数,这样我们可以在编译时检查类型,避免了运行时类型转换的麻烦和潜在的...