代码及说明:

/**
* @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. 判断js引擎是javascriptCore或者v8

    来由   纯粹的无聊,一直在搜索JavaScriptCore和SpiderMonkey的一些信息,却无意中学习了如何在ios的UIWebView中判断其js解析引擎的方法: if (window.de ...

  2. java多线程--同步屏障CyclicBarrier的使用

    CyclicBarrier的概念理解: CyclicBarrier的字面上的意思是可循环的屏障,是java并发包java.util.concurrent 里的一个同步工具类,在我下载的JDK1.6的中 ...

  3. 解决新版Android studio导入微信支付和支付宝官方Demo的问题

    最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...

  4. STemwin汉字显示

    硬件环境: STM32F429,电容屏800X480 5点触控RGB屏幕 ,SPI flash: 软件环境: UCOSIII,STemwin: 汉字显示方法: 1.在SPIflash中装在字库XBF_ ...

  5. 怎么调试lua性能

    怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...

  6. EF 在controller弹出提示消息

    第一种方式: return Content("<script>alert('此名称课程再次班级中已经存在!');window.location.href = 'Course/Cr ...

  7. Pyc 是什么东东

    在众多语言中, 最终我们可以将语言分为编译性语言和解释性语言两种 编译性语言,也就是机器语言, 是机器能读的懂的语言, 像C语言, 其实高级语言都是基于C语言的基础之上运行的 解释性语言, 不同于编译 ...

  8. The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory

    The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory 这是由于项目里面的一些 ...

  9. 安装XAMPP遇到的问题及解决方法

    1.XAMPP无法启动Apache Xampp的获得和安装都十分简单,你只要到以下网址: http://www.apachefriends.org/zh_cn/xampp.html 下载xampp即可 ...

  10. JDK1.8 HashMap 源码分析

    一.概述 以键值对的形式存储,是基于Map接口的实现,可以接收null的键值,不保证有序(比如插入顺序),存储着Entry(hash, key, value, next)对象. 二.示例 public ...