代码及说明:

/**
* @author zsm
* @date 2016年11月2日 下午11:23:30
* @version 1.0
* @parameter
* @return
*/
// JDK5开始支持泛型。泛型(类、接口、方法);泛型通配符、通配符上限、通配符下限
class _16_Generic {
// 泛型
List<String> strListStand = new ArrayList<String>();
// 泛型菱形语法(JDK7后初始化时泛型的具体类型可省略,自动判断)
List<String> strList = new ArrayList<>(); // 泛型类、接口
public interface Fruit<T> {
void add(T fruit);
} public interface MyMap<K, V> {
Set<K> keySet(); V put(K key, V value);
} public static class Apple<T> {
private T info; public Apple() {// 不能再写成Apple<T> } public Apple(T info) {
this.info = info;
} public T getInfo() {
return this.info;
} // 静态方法、静态初始化块、静态变量声明和初始化中不能使用类的泛型形参,静态类或接口定义处则可以
// static T name;//报错
// public static void bar(T msg) {}
// static {T name = "xiaoming";} // 静态方法不能使用类的类型参数,除非该静态方法是个泛型方法
public static <E, F> void ttt(E name, F age) {
;
}
} // 实现泛型接口或继承泛型类时:若新类不是泛型类,则父类(接口)必须指定类型实参而不能仍是类型形参;若新类仍是泛型类则父类(接口)可以仍用类型形参
public class A1 extends Apple<String> {// 不能再写成Apple<T>
public String getInfo() {
return super.info;
}
} public class A2<T> extends Apple<T> {
public T getInfo() {
return super.info;
}
} // 带泛型形参的类不会随着类型实参的不同而成为不同的类,接口亦然
static void testClassEqual() {
System.out.println((new Apple<String>()).getClass() == (new Apple<Integer>()).getClass());// true
List<String> strList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(strList.getClass() == intList.getClass());// true
} // 若Foo是Bar的子类,则Foo[]是Bar[]的子类,但List<Foo>却不是List<Bar>的子类。可以使用泛型通配符:?,
public void wildcardTest1(List<Object> c) {// 调用时只能传入List<Object>参数,不可传入List<String>等参数,因为后者不是前者的子类
for (int i = 0; i < c.size(); i++) {
System.out.println(c.get(i));
}
} public void wildcardTest2(List<?> c) {// 此时可传入List<String>等参数,但只可从c读不可往里写,因为c类型不定。即带类型通配符定义的对象只可读不可写
for (int i = 0; i < c.size(); i++) {
System.out.println(c.get(i));
// c.add(new Object());//编译错误,不可往c里写,因为c里元素类型未定
}
} // 类型通配符上限
public abstract class Shape {
public abstract void draw(MyCanvas c);
} public class Circle extends Shape {
@Override
public void draw(MyCanvas c) {
// TODO Auto-generated method stub
System.out.println("draw a circle on " + c);
}
} public class Rectangle extends Shape {
@Override
public void draw(MyCanvas c) {
// TODO Auto-generated method stub
System.out.println("draw a rectangle on " + c);
}
} public class MyCanvas {
public void drawAll0(List<?> shapes) {// 使用通配符时类型未定,所以访问每个元素只能用终极父类Object,这导致得进行麻烦的强制类型转换
for (Object obj : shapes) {
Shape s = (Shape) obj;
s.draw(this);
}
} public void drawAll1(List<? extends Shape> shapes) {// 使用通配符上限,从而知道元素元素类型的终极父类是Shape,这样不用进行强转。至多可以有一个类上限、多个接口上限,类上限需放最前。
for (Shape s : shapes) {
s.draw(this);
}
}
} // 泛型方法:方法中所用类型形参不要求在类声明中先出现该类型形参;类型形参位于方法修饰符和返回值之间;与泛型类、接口不同的是,无须在调用泛型方法时显式指明实参类型
public <T> void fromArrayToCollection(T[] a, Collection<T> c) {// a的实参可以是T[]的子类型
for (T o : a) {
c.add(o);
}
} public void test_fromArrayToCollection() {
fromArrayToCollection((new Object[10]), new ArrayList<Object>());
fromArrayToCollection((new Integer[10]), new ArrayList<Object>());
fromArrayToCollection((new Integer[10]), new ArrayList<>());// 与泛型类、接口不同的是,无须在调用泛型方法前显式指明实参类型(指在方法名前),编译器自己确定
fromArrayToCollection((new Integer[10]), new ArrayList<Number>());
// fromArrayToCollection((new Integer[10]), new ArrayList<String>());//编译错误
} // 泛型方法和类型通配符:方法参数间或返回值与参数间存在类型依赖关系(如子类)时采用泛型方法,否则类型参数只用一次,没有存在的必要,可以改用类型通配符。
public <T, S extends T> void copy1(List<T> des, List<S> src) {// S仅用了一次且与其他参数间没有依赖关系,因此没有存在的必要,改为下面的方法。
for (S s : src) {
des.add(s);
}
} public <T> void copy2(List<T> des, List<? extends T> src) {// 去掉S,改为使用类型通配符上限。
for (T t : src) {
des.add(t);
}
} // 泛型方法 ———— 泛型构造器
class Foo<E> {
public <T> Foo(T t) {
System.out.println(t);
} public void add(E e) { }
} public void test_genericConstructor() {
new Foo("good");
new Foo(1);
new <String>Foo("good");// 显示指定构造方法类型形参的实际类型
new <String>Foo<Integer>("good");// 又指定了类的类型形参的实际类型
new Foo<>("good");// 菱形语法
// new<String> Foo<>(1);// 如果显示指定了构造器类型形参的类型,则不可用菱形语法 Foo<Integer> p1 = new <String>Foo("good");
Foo<Integer> p2 = new <String>Foo<Integer>("good");
Foo<Integer> p3 = new Foo<Integer>("good");
// Foo<Integer> p4 = new<String> Foo<>("good");//如果显示指定了构造器类型形参的类型,则不可用菱形语法
} // 类型通配符下限。
// 返回最后一个元素,类型不可丢。上面的copy2方法如果要返回最后一个被复制的元素,则返回的会是des中元素的类型T,这样就丢失了src的类型即S。可以通过修改copy1解决,也可以通过通配符下限解决。
public <T, S extends T> S copy3(List<T> des, List<S> src) {// S仅用了一次且与其他参数间没有依赖关系,因此没有存在的必要,改为下面的方法。
int i = 0;
for (i = 0; i < src.size(); i++) {
des.add(src.get(i));
}
return src.get(i - 1);
} public <T> T copy4(List<? super T> des, List<T> src) {// 去掉S,改为类型通配符下限。
int i = 0;
for (i = 0; i < src.size(); i++) {
des.add(src.get(i));
}
return src.get(i - 1);
} // 檫除与转换:带泛型声明的类间转换
public static void test_Transform() {
List list;// 不指定实际类型参数,为raw type,默认为上限类型,此为Object
List<Integer> listInteger = new ArrayList<Integer>();
listInteger.add(1);
listInteger.add(2);
list = listInteger;// List<Integer>对象赋给未指定类型的List,原始类型丢失,变为Object List<String> listStr = list;// 编译没问题,只有警告:"未经检查的转换"
System.out.println(listStr.get(0));// 但访问里面元素,会发生运行时异常
} public static void main(String[] args) {
// TODO Auto-generated method stub } }

Java泛型及实践的更多相关文章

  1. Java 理论和实践: 了解泛型

    转载自 : http://www.ibm.com/developerworks/cn/java/j-jtp01255.html 表面上看起来,无论语法还是应用的环境(比如容器类),泛型类型(或者泛型) ...

  2. Java 理论和实践: 了解泛型 识别和避免学习使用泛型过程中的陷阱

    Brian Goetz (brian@quiotix.com), 首席顾问, Quiotix 简介: JDK 5.0 中增加的泛型类型,是 Java 语言中类型安全的一次重要改进.但是,对于初次使用泛 ...

  3. Java深度历险(五)——Java泛型

      作者 成富 发布于 2011年3月3日 | 注意:QCon全球软件开发大会(北京)2016年4月21-23日,了解更多详情!17 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件 ...

  4. java 深度探险 java 泛型

    Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在JD ...

  5. Java学习笔记(二一)——Java 泛型

    [前面的话] 最近脸好干,掉皮,需要买点化妆品了. Java泛型好好学习一下. [定义] 一.泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个 ...

  6. Java 泛型(Generics)

    Generics, 类似C++中的模版. 允许在定义类和接口的时候使用类型参数(type parameters), 声明的类型参数在使用的时候用具体的类型来替换. 如 ArrayList<Str ...

  7. 10个精妙的Java编码最佳实践

    这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...

  8. 转:理解Java泛型

    JDK 5.0 中增加的泛型类型,是 Java 语言中类型安全的一次重要改进.但是,对于初次使用泛型类型的用户来说,泛型的某些方面看起来可能不容易明白,甚至非常奇怪.在本月的“Java 理论和实践”中 ...

  9. java泛型总结(类型擦除、伪泛型、陷阱)

    JDK1.5开始实现了对泛型的支持,但是java对泛型支持的底层实现采用的是类型擦除的方式,这是一种伪泛型.这种实现方式虽然可用但有其缺陷. <Thinking in Java>的作者 B ...

随机推荐

  1. DotNet生成随机数的一些方法

    在项目开发中,一般都会使用到“随机数”,但是在DotNet中的随机数并非真正的随机数,可在一些情况下生成重复的数字,现在总结一下在项目中生成随机数的方法. 1.随机布尔值: /// <summa ...

  2. 【分布式】Zookeeper在大型分布式系统中的应用

    一.前言 上一篇博文讲解了Zookeeper的典型应用场景,在大数据时代,各种分布式系统层出不穷,其中,有很多系统都直接或间接使用了Zookeeper,用来解决诸如配置管理.分布式通知/协调.集群管理 ...

  3. SpingMVC 核心技术帮助文档

    声明:本篇文档主要是用于参考帮助文档,没有实例,但几乎包含了SpringMVC 4.2版本的所有核心技术,当前最新版本是4.3,4.2的版本已经经是很新的了,所以非常值得大家一读,对于读完这篇文档感觉 ...

  4. 导出BOM表

    1.Report->Bill of Materials for Project 将Value拖上左上角的Grouped Columns 2.在Excel表中全选器件,右键设置"设置单元 ...

  5. C#开机自动启动程序代码

    新建一个winform拖一个checkbox进来.. 然后设置它的changed事件. 已经测试过,可以直接复制使用. private void checkBox1_CheckedChanged(ob ...

  6. wamp集成环境开启rewrite伪静态支持

    wamp集成环境在安装完后,默认是没有开启伪静态的,所以有时把项目部署进去时如果源码里包含.htaccess文件的话,可能会出现500错误,这一般是因为不支持伪静态造成的,解决这个问题的办法就是开启伪 ...

  7. iOS从零开始学习直播之音频2.后台播放和在线播放

    本篇主要讲音频的后台播放和在线播放. 后台播放   上一篇写的工程运行之后程序退至后台,发现运行不了,歌停止了,这显然不行,音乐后台播放是标配啊.今天就来讲一下后台播放. 1.在plist文件里,告诉 ...

  8. Unable to simultaneously satisfy constraints.

    在进行版本的迭代更新时,新功能需求需要对主页面的UI进行重新的布局,但是,报了错误,出了好多约束方面的问题: Unable to simultaneously satisfy constraints. ...

  9. IT技术风向标

    2016 stackoverflow的统计 : http://stackoverflow.com/research/developer-survey-2016

  10. [译]Angular2 和TypeScript -- 一次简要的预览

    原文链接:https://www.infoq.com/articles/Angular2-TypeScript-High-Level-Overview 作者:  Yakov Fain Posted o ...