Java泛型及实践
代码及说明:
/**
* @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泛型及实践的更多相关文章
- Java 理论和实践: 了解泛型
转载自 : http://www.ibm.com/developerworks/cn/java/j-jtp01255.html 表面上看起来,无论语法还是应用的环境(比如容器类),泛型类型(或者泛型) ...
- Java 理论和实践: 了解泛型 识别和避免学习使用泛型过程中的陷阱
Brian Goetz (brian@quiotix.com), 首席顾问, Quiotix 简介: JDK 5.0 中增加的泛型类型,是 Java 语言中类型安全的一次重要改进.但是,对于初次使用泛 ...
- Java深度历险(五)——Java泛型
作者 成富 发布于 2011年3月3日 | 注意:QCon全球软件开发大会(北京)2016年4月21-23日,了解更多详情!17 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件 ...
- java 深度探险 java 泛型
Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在JD ...
- Java学习笔记(二一)——Java 泛型
[前面的话] 最近脸好干,掉皮,需要买点化妆品了. Java泛型好好学习一下. [定义] 一.泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个 ...
- Java 泛型(Generics)
Generics, 类似C++中的模版. 允许在定义类和接口的时候使用类型参数(type parameters), 声明的类型参数在使用的时候用具体的类型来替换. 如 ArrayList<Str ...
- 10个精妙的Java编码最佳实践
这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...
- 转:理解Java泛型
JDK 5.0 中增加的泛型类型,是 Java 语言中类型安全的一次重要改进.但是,对于初次使用泛型类型的用户来说,泛型的某些方面看起来可能不容易明白,甚至非常奇怪.在本月的“Java 理论和实践”中 ...
- java泛型总结(类型擦除、伪泛型、陷阱)
JDK1.5开始实现了对泛型的支持,但是java对泛型支持的底层实现采用的是类型擦除的方式,这是一种伪泛型.这种实现方式虽然可用但有其缺陷. <Thinking in Java>的作者 B ...
随机推荐
- 判断js引擎是javascriptCore或者v8
来由 纯粹的无聊,一直在搜索JavaScriptCore和SpiderMonkey的一些信息,却无意中学习了如何在ios的UIWebView中判断其js解析引擎的方法: if (window.de ...
- java多线程--同步屏障CyclicBarrier的使用
CyclicBarrier的概念理解: CyclicBarrier的字面上的意思是可循环的屏障,是java并发包java.util.concurrent 里的一个同步工具类,在我下载的JDK1.6的中 ...
- 解决新版Android studio导入微信支付和支付宝官方Demo的问题
最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...
- STemwin汉字显示
硬件环境: STM32F429,电容屏800X480 5点触控RGB屏幕 ,SPI flash: 软件环境: UCOSIII,STemwin: 汉字显示方法: 1.在SPIflash中装在字库XBF_ ...
- 怎么调试lua性能
怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...
- EF 在controller弹出提示消息
第一种方式: return Content("<script>alert('此名称课程再次班级中已经存在!');window.location.href = 'Course/Cr ...
- Pyc 是什么东东
在众多语言中, 最终我们可以将语言分为编译性语言和解释性语言两种 编译性语言,也就是机器语言, 是机器能读的懂的语言, 像C语言, 其实高级语言都是基于C语言的基础之上运行的 解释性语言, 不同于编译 ...
- The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory
The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory 这是由于项目里面的一些 ...
- 安装XAMPP遇到的问题及解决方法
1.XAMPP无法启动Apache Xampp的获得和安装都十分简单,你只要到以下网址: http://www.apachefriends.org/zh_cn/xampp.html 下载xampp即可 ...
- JDK1.8 HashMap 源码分析
一.概述 以键值对的形式存储,是基于Map接口的实现,可以接收null的键值,不保证有序(比如插入顺序),存储着Entry(hash, key, value, next)对象. 二.示例 public ...