千家信息网

Java中什么是Generics

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章给大家分享的是有关Java中什么是Generics的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一.什么是Generics?Generics可以称之为参数类型(pa
千家信息网最后更新 2026年11月02日Java中什么是Generics

这篇文章给大家分享的是有关Java中什么是Generics的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

  一.什么是Generics?

  Generics可以称之为参数类型(parameterized types),由编译器来验证从客户端将一种类型传送给某一对象的机制。如Java.util.ArrayList,

  编译器可以用Generics来保证类型安全。
在我们深入了解Generics之前,我们先来看一看当前的java 集合框架(Collection)。在j2SE1.4中所有集合的Root Interface是Collection

Collections example without genericity: Example 1


1 protected void collectionsExample() {
2 ArrayList list = new ArrayList();
3 list.add(new String("test string"));
4 list.add(new Integer(9)); // purposely placed here to create a runtime ClassCastException
5 inspectCollection(list);
6 }
7
8
9 protected void inspectCollection(Collection aCollection) {
10 Iterator i = aCollection.iterator();
11 while (i.hasNext()) {
12 String element = (String) i.next();
13 }
14 }



  以上的样例程序包含的两个方法,collectionExample方法建立了一个简单的集合类型ArrayList,并在ArrayList中增加了一个String和一个Integer对象.而在inspecCollection方法中,我们迭代这个ArrayList用String进行Cast。我们看第二个方法,就出现了一个问题,Collection在内部用的是Object,而我们要取出Collection中的对象时,需要进行Cast,那么开发者必需用实际的类型进行Cast,像这种向下造型,编译器无

  法进行检查,如此一来我们就要冒在代码在运行抛出ClassCastException的危险。我们看inspecCollection方法,编译时没有问题,但在运行时就会抛出ClassCastException异常。所以我们一定要远离这个重大的运行时错误


  二.使用Generics
  从上一章节中的CassCastException这种异常,我们期望在代码编译时就能够捕捉到,下面我们使用范型修改上一章的样例程序。
//Example 2

1 protected void collectionsExample() {
2 ArrayList

list = new ArrayList();
3 list.add(new String("test string"));
4 // list.add(new Integer(9)); this no longer compiles
5 inspectCollection(list);
6 }
7
8
9 protected void inspectCollection(CollectionaCollection) {
10 Iteratori = aCollection.iterator();
11 while(i.hasNext()) {
12 String element = i.next();
13 }
14 }



  从上面第2行我们在创建ArrayList时使用了新语法,在JDK1.5中所有的Collection都加入了Generics的声明。例:
//Example 3

1 public class ArrayListextends AbstractList{
2 // details omitted...
3 public void add(E element) {
4 // details omitted
5 }
6 public Iteratoriterator() {
7 // details omitted
8 }
9 }



  这个E是一个类型变量,并没有对它进行具体类型的定义,它只是在定义ArrayList时的类型占位符,在Example 2中的我们在定义ArrayList的实

  例时用String绑定在E上,当我们用add(E element)方法向ArrayList中增加对象时, 那么就像下面的写法一样: public void add(String element);因为在ArrayList所有方法都会用String来替代E,无论是方法的参数还是返回值。这时我们在看Example 2中的第四行,编译就会反映出编译错误。
所以在java中增加Generics主要的目的是为了增加类型安全。

  通过上面的简单的例子我们看到使用Generics的好处有:
  1.在类型没有变化时,Collection是类型安全的。
  2.内在的类型转换优于在外部的人工造型。
  3.使Java 接口更加强壮,因为它增加了类型。
  4.类型的匹配错误在编译阶段就可以捕捉到,而不是在代码运行时。

  受约束类型变量
虽然许多Class被设计成Generics,但类型变量可以是受限的
public class C1{ }
public class C2{ }
第一个T变量必须继承Number,第二个T必须继承Person和实现Comparable

  三.Generics 方法

  像Generics类一样,方法和构造函数也可以有类型参数。方法的参数的返回值都可以有类型参数,进行Generics。
//Example 4

1 publicT max(T t1, T t2) {
2 if (t1.compareTo(t2) > 0)
3 return t1;
4 else return t2;
5 }



  这里,max方法的参数类型为单一的T类型,而T类型继承了Comparable,max的参数和返回值都有相同的超类。下面的Example 5显示了max方法的几个约束。
//Example 5 

1 Integer iresult = max(new Integer(100), new Integer(200));
2 String sresult = max("AA", "BB");
3 Number nresult = max(new Integer(100), "AAA"); // does not compile



在Example 5第1行参数都为Integer,所以返回值也是Integer,注意返回值没有进行造型。
在Example 5第2行参数都为String,所以返回值也是String,注意返回值没有进行造型。以上都调用了同一个方法。
在Example 5第3行产生以下编译错误:
Example.java:10: incompatible types
found : java.lang.Object&java.io.Serializable&java.lang.Comparable
required: java.lang.Number
Number nresult = max(new Integer(100), "AAA");

  这个错误发生是因为编译器无法确定返回值类型,因为String和Integer都有相同的超类Object,注意就算我们修正了第三行,这行代码在运行仍然会报错,因为比较了不同的对象。

  四.向下兼容
  任何一个新的特色在新的JDK版本中出来后,我们首先关心的是如何于以前编写的代码兼容。也就是说我们编写的Example 1程序不需要任何的改变就可以运行,但是编译器会给出一个"ROW TYPE"的警告。在JDK1.4中编写的代码如何在JVM1.5中完全兼容运行,我们要人工进行一个:Type erasure处理过程

  五.通配符

//Example 6

ListstringList = new ArrayList(); //1
ListobjectList = stringList ;//2
objectList .add(new Object()); // 3
String s = stringList .get(0);//4



  乍一看,Example

  6是正确的。但stringList本意是存放String类型的ArrayList,而objectList中可以存入任何对象,当在第3行进行处理时,stringList也就无法保证是String类型的ArrayList,此时编译器不允许这样的事出现,所以第3行将无法编译。

//Example 7

void printCollection(Collectionc)
{ for (Object e : c) {
System.out.println(e);
}}



  Example 7的本意是打印所有Collection的对象,但是正如Example 6所说的,编译会报错,此时就可以用通配符"?"来修改Example 7

//Example 8

void printCollection(Collection c)
{ for (Object e : c) {
System.out.println(e);
}}



Example 8中所有Collection类型就可以方便的打印了

  有界通配符(上界)(下界)

  六.创建自己的范型
以下代码来自http://www.java2s.com/ExampleCode/Language-Basics
1.一个参数的Generics
//Example 9(没有使用范型)

class NonGen {
Object ob; // ob is now of type Object
// Pass the constructor a reference to
// an object of type Object
NonGen(Object o) {
ob = o;
}
// Return type Object.
Object getob() {
return ob;
}
// Show type of ob.
void showType() {
System.out.println("Type of ob is " +
ob.getClass().getName());
}
}
// Demonstrate the non-generic class.
public class NonGenDemo {
public static void main(String args[]) {
NonGen iOb;
// Create NonGen Object and store
// an Integer in it. Autoboxing still occurs.
iOb = new NonGen(88);
// Show the type of data used by iOb.
iOb.showType();
// Get the value of iOb.
// This time, a cast is necessary.
int v = (Integer) iOb.getob();
System.out.println("value: " + v);
System.out.println();
// Create another NonGen object and
// store a String in it.
NonGen strOb = new NonGen("Non-Generics Test");
// Show the type of data used by strOb.
strOb.showType();
// Get the value of strOb.
// Again, notice that a cast is necessary.
String str = (String) strOb.getob();
System.out.println("value: " + str);
// This compiles, but is conceptually wrong!
iOb = strOb;
v = (Integer) iOb.getob(); // runtime error!
}
}



//Example 10(使用范型)

class Example1{
private T t;
Example1(T o){
this.t=o;
}
T getOb(){
return t;
}
void ShowObject(){
System.out.println("对象的类型是:"+t.getClass().getName());
}
}
public class GenericsExample1 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Example1examplei=new Example1(100);
examplei.ShowObject();
System.out.println("对象是:"+examplei.getOb());
Example1examples=new Example1("Bill");
examples.ShowObject();
System.out.println("对象是:"+examples.getOb());
}

}



  我们来看Example 9没有使用范型,所以我们需要进行造型,而Example 10我们不需要任何的造型

2.二个参数的Generics

//Example 11

class TwoGen{
T ob1;
V ob2;
// Pass the constructor a reference to
// an object of type T.
TwoGen(T o1, V o2) {
ob1 = o1;
ob2 = o2;
}
// Show types of T and V.
void showTypes() {
System.out.println("Type of T is " +
ob1.getClass().getName());
System.out.println("Type of V is " +
ob2.getClass().getName());
}
T getob1() {
return ob1;
}
V getob2() {
return ob2;
}
}

public class GenericsExampleByTwoParam {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TwoGentgObj =
new TwoGen(88, "Generics");
// Show the types.
tgObj.showTypes();
// Obtain and show values.
int v = tgObj.getob1();
System.out.println("value: " + v);
String str = tgObj.getob2();
System.out.println("value: " + str);
}

}



3.Generics的Hierarchy

//Example 12

class Stats{
T[] nums; // array of Number or subclass
// Pass the constructor a reference to
// an array of type Number or subclass.
Stats(T[] o) {
nums = o;
}
// Return type double in all cases.
double average() {
double sum = 0.0;
for(int i=0; i < nums.length; i++)
sum += nums.doubleValue();
return sum / nums.length;
}
}
public class GenericsExampleByHierarchy {


/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

Integer inums[] = { 1, 2, 3, 4, 5 };
Statsiob = new Stats(inums);
double v = iob.average();
System.out.println("iob average is " + v);
Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Statsdob = new Stats(dnums);
double w = dob.average();
System.out.println("dob average is " + w);
// This won't compile because String is not a
// subclass of Number.
// String strs[] = { "1", "2", "3", "4", "5" };
// Statsstrob = new Stats(strs);
// double x = strob.average();
// System.out.println("strob average is " + v);
}
}



  4.使用通配符
//Example 14

class StatsWildCard{
T[] nums; // array of Number or subclass
// Pass the constructor a reference to
// an array of type Number or subclass.
StatsWildCard(T[] o) {
nums = o;
}
// Return type double in all cases.
double average() {
double sum = 0.0;
for (int i = 0; i < nums.length; i++)
sum += nums
.doubleValue();
return sum / nums.length;
}
// Determine if two averages are the same.
// Notice the use of the wildcard.
boolean sameAvg(StatsWildCard ob) {
if (average() == ob.average())
return true;
return false;
}
}

public class GenericsExampleByWildcard {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer inums[] = { 1, 2, 3, 4, 5 };
StatsWildCardiob = new StatsWildCard(inums);
double v = iob.average();
System.out.println("iob average is " + v);
Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
StatsWildCarddob = new StatsWildCard(dnums);
double w = dob.average();
System.out.println("dob average is " + w);
Float fnums[] = { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F };
StatsWildCardfob = new StatsWildCard(fnums);
double x = fob.average();
System.out.println("fob average is " + x);
// See which arrays have same average.
System.out.print("Averages of iob and dob ");
if (iob.sameAvg(dob))
System.out.println("are the same.");
else
System.out.println("differ.");
System.out.print("Averages of iob and fob ");
if (iob.sameAvg(fob))
System.out.println("are the same.");
else
System.out.println("differ.");

}

}



  5.使用边界通配符
//Example 15

class TwoD {
int x, y;
TwoD(int a, int b) {
x = a;
y = b;
}
}
// Three-dimensional coordinates.
class ThreeD extends TwoD {
int z;
ThreeD(int a, int b, int c) {
super(a, b);
z = c;
}
}
// Four-dimensional coordinates.
class FourD extends ThreeD {
int t;
FourD(int a, int b, int c, int d) {
super(a, b, c);
t = d;
}
}
// This class holds an array of coordinate objects.
class Coords{
T[] coords;
Coords(T[] o) { coords = o; }
}
// Demonstrate a bounded wildcard.
public class BoundedWildcard {
static void showXY(Coords c) {
System.out.println("X Y Coordinates:");
for(int i=0; i < c.coords.length; i++)
System.out.println(c.coords.x + " " +
c.coords
.y);
System.out.println();
}
static void showXYZ(Coords c) {
System.out.println("X Y Z Coordinates:");
for(int i=0; i < c.coords.length; i++)
System.out.println(c.coords.x + " " +
c.coords
.y + " " +
c.coords.z);
System.out.println();
}
static void showAll(Coords c) {
System.out.println("X Y Z T Coordinates:");
for(int i=0; i < c.coords.length; i++)
System.out.println(c.coords
.x + " " +
c.coords.y + " " +
c.coords
.z + " " +
c.coords.t);
System.out.println();
}
public static void main(String args[]) {
TwoD td[] = {
new TwoD(0, 0),
new TwoD(7, 9),
new TwoD(18, 4),
new TwoD(-1, -23)
};
Coordstdlocs = new Coords(td);
System.out.println("Contents of tdlocs.");
showXY(tdlocs); // OK, is a TwoD
// showXYZ(tdlocs); // Error, not a ThreeD
// showAll(tdlocs); // Erorr, not a FourD
// Now, create some FourD objects.
FourD fd[] = {
new FourD(1, 2, 3, 4),
new FourD(6, 8, 14, 8),
new FourD(22, 9, 4, 9),
new FourD(3, -2, -23, 17)
};
Coordsfdlocs = new Coords(fd);
System.out.println("Contents of fdlocs.");
// These are all OK.
showXY(fdlocs);
showXYZ(fdlocs);
showAll(fdlocs);
}
}




6.ArrayList的Generics
//Example 16

public class ArrayListGenericDemo {
public static void main(String[] args) {
ArrayListdata = new ArrayList();
data.add("hello");
data.add("goodbye");

// data.add(new Date()); This won't compile!

Iteratorit = data.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}



7.HashMap的Generics
//Example 17

public class HashDemoGeneric {
public static void main(String[] args) {
HashMapmap = new HashMap();

map.put(1, "Ian");
map.put(42, "Scott");
map.put(123, "Somebody else");

String name = map.get(42);
System.out.println(name);
}
}



8.接口的Generics
//Example 18

interface MinMax> {
T min();
T max();
}
// Now, implement MinMax
class MyClass> implements MinMax{
T[] vals;
MyClass(T[] o) { vals = o; }
// Return the minimum value in vals.
public T min() {
T v = vals[0];
for(int i=1; i < vals.length; i++)
if(vals
.compareTo(v) < 0) v = vals;
return v;
}
// Return the maximum value in vals.
public T max() {
T v = vals[0];
for(int i=1; i < vals.length; i++)
if(vals
.compareTo(v) > 0) v = vals;
return v;
}
}
public class GenIFDemo {
public static void main(String args[]) {
Integer inums[] = {3, 6, 2, 8, 6 };
Character chs[] = {'b', 'r', 'p', 'w' };
MyClassiob = new MyClass(inums);
MyClasscob = new MyClass(chs);
System.out.println("Max value in inums: " + iob.max());
System.out.println("Min value in inums: " + iob.min());
System.out.println("Max value in chs: " + cob.max());
System.out.println("Min value in chs: " + cob.min());
}
}



9.Exception的Generics
//Example 20

interface Executor{
void execute() throws E;
}

public class GenericExceptionTest {
public static void main(String args[]) {
try {
Executore =
new Executor() {
public void execute() throws IOException
{
// code here that may throw an
// IOException or a subtype of
// IOException
}
};

e.execute();
} catch(IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
}
}
}

感谢各位的阅读!关于"Java中什么是Generics"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

类型 方法 编译 参数 对象 代码 运行 编译器 造型 范型 通配符 错误 变量 安全 程序 面的 相同 人工 内容 接口 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 湖北九亚互联网络科技有限公司 广东猪兼强互联网科技有限公司 科技服务与互联网 亿策互联网科技 贷财互联网科技 银优互联网科技有限公司 北京禾田雨橡互联网科技 互联网金融 科技创新 重庆科技学院互联网 滨湖区互联网智能科技产品供应 互联网之后的科技是什么 互联网还是高科技吗 岳阳华臻互联网科技有限公司 互联网金融科技名词解释 山东星卡互联网科技有限公司官网 广州富喜互联网络科技 互联网科技股为什么大涨 上海万顺科技互联网有限公司招聘 悟空问答互联网科技 恒生科技互联网指数十大成分股 互联网科技工作委员会副主任毛军 互联网科技公司的优势 浩特互联网科技 互联网科技公司介绍 港股科技和互联网 杭州壁岐互联网科技有限公司 南博望互联网科技有限公司 互联网金融科技名词解释 互联网领先科技宣传片 广州智享互联网科技
0