`
whitesock
  • 浏览: 483774 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Java Generic (1)

    博客分类:
  • SE
阅读更多

1 泛型类
    泛型允许对类型进行抽象,最常见的泛型类是容器类。例如:

List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for(String s: list) {
	System.out.println(s);
}

    以上例子中,如果试图向list中添加一个Integer对象,那么会导致编译错误。编译器会进行类型检查,这避免了使用非泛型容器类时常见的强制类型转换。泛型类是具有一个或者多个类型变量(type variable)的类。以下是个简单的例子:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Bag<E> {
	private List<E> bag = new ArrayList<E>();

	public Iterator<E> iterator() {
		return this.bag.iterator();
	}

	public boolean add(E e) {
		return this.bag.add(e);
	}

	public boolean remove(Object o) {
		return this.bag.remove(o);
	}
	
	public boolean contains(Object e) {
		return this.bag.contains(e);
	}

	public boolean addAll(Bag<? extends E> b) {
		return this.bag.addAll(b.bag);
	}
	
	public boolean removeAll(Bag<?> b) {
		return this.bag.removeAll(b.bag);
	}

	public boolean containsAll(Bag<?> b) {
		return this.bag.containsAll(b.bag);
	}
    
	public void clear() {
		this.bag.clear();
	}
   
   	List<E> getBag() {
		return this.bag;
	}
}
import java.util.Collections;
import java.util.Comparator;

public class Bags {
	public static <E> void sort(Bag<E> b, Comparator<? super E> c) {
		Collections.sort(b.getBag(), c);
	}

	public static <T extends Comparable<? super T>> T max(Bag<T> b) {
		return Collections.max(b.getBag());
	}

	public static <E> void copy(Bag<E> dest, Bag<? extends E> src) {
		dest.addAll(src);
	}
}

    需要注意的是,不能抛出或者捕获泛型类的实例,泛型类继承自Throwable也是不合法的。此外也不能声明泛型类实例的数组,例如以下代码会造成编译错误:

Bag<Integer> b3[] = new Bag<Integer>[10]; // Cannot create a generic array of Bag<Integer>

 

2 泛型方法
    泛型方法是指带有类型参数的方法,类型变量的位置是修饰符和返回类型之间。在调用泛型方法的时候,具体类型的位置是方法名前的尖括号中,在绝大多数的情况下,由于编译器可以判断出具体类型,因此也可以省略具体类型。以下是个简单的例子:

public class Base {
    public String getName() {
	    return "Base";
    }

    public static <T> void print(T t) {
        System.out.println(t.toString());
    }
 
    public static void main(String args[]) {
	    Base base = new Base();
	    Base.<Base>print(base);
	    Base.print(base);
    }
}

    以上例子中的print方法内只能调用T从Object类继承的方法。如果希望将T限定为Base及其子类,那么可以使用extends设定上限,或者使用super设定下限(C++中不能限定参数变量的类型),例如:

public static <T extends Base> void print(T t) {
	System.out.println(t.getName());
}

    类型变量也可以有多个限定,限定类型用&分割。如果限定类型可以包含多个接口,但是至多有一个类(单继承),如果有一个类,那么它必须是第一个限定类型。例如: 

T extends Comparable & Serializable

 

3 擦除

    编译器会为每个泛型类型自动提供一个原始类型(raw type)。其类型变量会被擦除(因此Java泛型没有C++模板类的代码膨胀问题),并用其限定类型代替,如果没有限定类型,那么使用Object。不能使用原始数据类型作为类型变量,例如没有Bag<int>,但是可以有Bag<Integer>。 由于类型变量会被擦除,因此不管泛型类的类型变量是什么,它的所有实例的运行时类是相同的,例如以下代码的输出如下:

Bag<Integer> b1 = new Bag<Integer>();
Bag<String> b2 = new Bag<String>();
System.out.println(b1.getClass());
System.out.println(b2.getClass());
System.out.println(b1.getClass() == b2.getClass());

    class Bag
    class Bag
    true

    由于类的静态成员变量和成员方法也被类的所有实例共享,因此不能在类的静态成员变量和成员方法中引用类型变量。例如以下的代码会导致编译错误:

public class Bag<E> {
	private static E INSTANCE; // Cannot make a static reference to the non-static type E

	public static E getInstance() { // Cannot make a static reference to the non-static type E
		return INSTANCE;
	}
}

    不能通过类型变量构造实例,但是可以通过Class.newInstance和Array.newInstance来构造实例。例如以下的代码会造成编译错误:

public Bag() {
	E e1 = new E(); // Cannot instantiate the type E
	E e2[] = new E[10]; 
}

    在擦除后,也不能引起冲突。考虑如下代码:

public class Bag<E> {
	public boolean equals(E e) { // Name clash: The method equals(E) of type Bag<E> has the same erasure as equals(Object) of type Object but does not override it
		return true;
	}
}

    以上的Bag类的类型变量被擦除后的代码如下:

public class Bag<E> {
	public boolean equals(Object e) {
		return true;
	}
}

    其equals方法与Object.equals(Object obj)方法冲突。

6
4
分享到:
评论

相关推荐

    Java - Generic

    在Java编程语言中,泛型(Generic)是一个强大的特性,它允许我们在编译时检查类型安全,并且可以消除运行时的类型转换。泛型引入的主要目的是提高代码的重用性、安全性和效率,同时减少类型转换的繁琐工作。这篇...

    Java Generic 介绍 (pdf)

    1. **泛型的基本概念**:泛型是Java中的一种模板类或接口,它允许开发者在定义类、接口和方法时使用类型参数,而不是具体的类型。这就像创建了一个可以适用于多种类型的通用容器。 2. **泛型的语法**:在类的声明中...

    Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

    Java1.5泛型指南中文版(Java1.5 GenericTutorial)

    Generic_MT4_java_generic_mt4_

    标题中的"Generic_MT4_java_generic_mt4_"暗示了一个与MetaTrader 4 (MT4)交易平台相关的编程项目,可能是一个自定义的智能交易系统(Expert Advisor,EA)或指标,使用了Java语言,并且具有通用性。这个“Generic_...

    Generic Variance java 源码

    Generic Variance java 源码

    Generic Stack java 源码

    Generic Stack java 源码

    Generic Programming for Scientific Computing in C++, Java, and C#

    ### 泛型编程在科学计算中的应用:C++、Java与C#的比较 #### 摘要概览 本文是一篇关于泛型编程在科学计算领域应用的研究论文。研究对比了Java、C#和C++三种语言在实现泛型(参数化类型)方面的表现,并重点介绍了...

    java-generic.rar_泛型

    在《java-generic.rar》压缩包中包含的《java generic.pdf》文件,很可能是详细阐述了以下几个关于Java泛型的核心知识点: 1. **类型参数化**:泛型的核心在于类型参数化,这使得我们可以在定义类、接口和方法时...

    android 浅复制和深复制-Java Generic Deep Copy 篇

    本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...

    Generic in java programming language

    ### Java泛型编程详解 #### 引言 Java 5引入了多项语言级别的扩展功能,其中最为重要的一项就是泛型(Generics)的引入。本文档旨在为读者介绍Java中的泛型概念及其用法。 如果你熟悉其他语言如C++中的模板...

    Generic22BW.zip

    "Generic22BW.zip"是一个压缩包文件,其命名方式暗示它可能是一个通用或标准的软件版本,"BW"可能是“Black and White”或者“Basic Version”的缩写,表明这可能是一个简化版或黑白主题的版本。从标签"Generic22...

    11.4java-泛型(Generic).md

    11.4java-泛型(Generic)

    velocity-tools-generic-3.1-API文档-中英对照版.zip

    标签:apache、velocity、tools、generic、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明...

    java高手真经 光盘源码

    java高手真经 全光盘源代码 打包rar 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例Hello...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性

    java泛型数组

    1. **泛型数组的创建**:在 Java 中,直接创建泛型数组是不可能的,而应当采用 `Array.newInstance` 或其他替代方案。 2. **类型擦除的影响**:Java 泛型在运行时会被擦除为其原始类型,这限制了泛型数组的使用。 3....

    collections-generic-4.01_and_looks-2.1.4

    该文件里包含两个.jar包: collections-generic-4.01.jar和looks-2.1.4.jar, 引入collections-generic-4.01.jar: 右击工程--》Build path ——》Add External JAR--&gt;选中collections-generic-4.01.jar --》OK 在源...

Global site tag (gtag.js) - Google Analytics