java泛型学习(2)
一:深入泛型使用。主要是父类和子类存在泛型的demo
/**
* 父类为泛型类
* @author 尚晓飞
* @date 2014-7-15 下午7:31:25
*
*
* 父类和子类的泛型。
* 【泛型的具体声明】
* (1)子类直接声明具体类型
* (2)使用时指定具体类型(new 对象时)
* (3)子类泛型>=父类泛型(个数,类型,顺序无关)
*
* 【泛型的确定】
* (1)属性:在父类中,泛型随父类泛型而定
* 子类中,泛型随子类泛型而定
* (2)重写方法中:
* 泛型全部随父类而定
* 【泛型的擦除】
* 父类和子类泛型要么同时擦除。统一object对待
* 子类不能擦除泛型,而父类存在泛型
*
*
* @param <T>
*/
public abstract class Father<T,T1> {
T name;
public abstract T test(T t);
} //子类声明时指定具体类型
//属性类型为具体类型
class Child1 extends Father<String,Integer>{ @Override//重写方法中,泛型全部随父类而定
public String test(String t) {
// TODO Auto-generated method stub
return null;
} } //子类为泛型类.类型在使用时确定(new 对象时)
//子类类型>=父类类型
class Child2<T1,T,T2> extends Father<T,T1>{
@Override
public T test(T t) {
// TODO Auto-generated method stub
return null;
}
} //子类为泛型类,父类不指定泛型,统一object对待,父类泛型的擦除
//子类和父类同时擦除泛型。
//子类不能单独擦除泛型,而父类不擦除泛型
class Child3<T1,T> extends Father{
T1 name2;//子类中属性,随子类泛型而定 @Override
public Object test(Object t) {
// TODO Auto-generated method stub
return null;
} } //这是报错的,子类擦除,父类使用泛型。编译通不过。
class Child extends Father<T, T1>{ }
二:泛型的一个误区使用demo
Student泛型类
public class Student<T> {
T javase;
T oracle; public T addStudent(T t1){
T sT=t1;
return sT ;
} public Student() {
super();
}
public Student(T javase, T oracle) {
super();
this.javase = javase;
this.oracle = oracle;
}
public T getJavase() {
return javase;
}
public void setJavase(T javase) {
this.javase = javase;
}
public T getOracle() {
return oracle;
}
public void setOracle(T oracle) {
this.oracle = oracle;
} }
测试Test类
泛型的擦除
* 【1】子类继承|实现时不指定泛型
* 【2】使用时不指定泛型
* 统一Object对待,但泛型不是object,编译时不会类型检查
* 编译器会发出警告,但不报错
/**
* 泛型的擦除
* 【1】子类继承|实现时不指定泛型
* 【2】使用时不指定泛型
* 统一Object对待,但泛型不是object,编译时不会类型检查
* 编译器会发出警告,但不报错
* @author 尚晓飞
* @date 2014-7-15 下午8:26:21
*
*/
public class Test {
public static void main(String[] args) {
Student stu1=new Student();//如果使用时不确定泛型类型,编译器会发出警告,但不算错;
Object sd=stu1.javase;//类型统一用object对待。相当于object,而不是指object Student<Object> stu2=new Student<Object>(); test1(stu1);//虽然没确定泛型,以object对待,只是相当于,但不确定。泛型擦除,编译时编译器不会类型检查。所以不报错
test1(stu2);//如果泛型指定是Object时,那么传入的实参的泛型必须是Object.此方法报错。泛型一旦确定,哪怕是指定Object,编译器会编译类型检查 test2(stu1);
test2(stu2); } //方法一
public static void test1(Student<Integer> st){}
//方法二
public static void test2(Student<?> st){}
}
java泛型的深入理解
在学习泛型之前,简单介绍下泛型的一些基本术语,以ArrayList<E>和ArrayList<Integer>做简要介绍:
整个成为ArrayList<E>泛型类型
ArrayList<E>中的 E称为类型变量或者类型参数
整个ArrayList<Integer> 称为参数化的类型
ArrayList<Integer>中的integer称为类型参数的实例或者实际类型参数
·ArrayList<Integer>中的<Integer>念为typeof Integer
ArrayList称为原始类型
以下为泛型擦除的概念和示例代码,帮助理解java泛型的原理
//【1】java的泛型是伪泛型,只是在编译时起作用,进行类型检查,可称为java的语法糖。
//【2】一旦编译通过,编译成内存中的class文件信息,jvm就将所有的泛型擦除。在jvm中的class信息是无泛型的,都统一是object
//【3】泛型擦除后的原始类型-->,什么是原始类型?原始类型(raw type)就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型。
//无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型变量被擦除(crased),
//并使用其限定类型(无限定的变量用Object)替换。
//【4】,类型检查就是针对引用的,谁是一个引用,用这个引用调用泛型方法,就会对这个引用调用的方法进行类型检测,而无关它真正引用的对象
//因此arryList3能添加Integer类型数据,而与new ArrayList<String>();对象无关,它只是开辟一个空间
ArrayList<String> arrayList1=new ArrayList<String>();
arrayList1.add("shangxiaofei"); ArrayList<Integer> arrayList2=new ArrayList<Integer>();
arrayList2.add(125);
//【4】
ArrayList arrayList3=new ArrayList<String>();
arrayList3.add(125); //【2】本身arrayList2中只能存放Integer类型的数据,但通过反射获取arrayList2的class信息,并操作add方法,却往里添加了字符串。
//证明了java泛型是伪泛型,只存在编译器检查语法错误和类型转换层面,一旦编译成class文件,所有泛型全部擦除
arrayList2.getClass().getMethod("add", Object.class).invoke(arrayList2, "zifuchuan");
//【1】虽然指定了不同的泛型,但类信息还是相同,说明java泛型是伪泛型。
System.out.println("Test.main()"+(arrayList1.getClass()==arrayList2.getClass()));
2、泛型中的?通配符的扩展
1:界定通配符的上边界
Vector<? extends 类型1> x = new Vector<类型2>();
类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的子类
Vector<? extends Number> x = new Vector<Integer>();//这是正确的
Vector<? extends Number> x = new Vector<String>();//这是错误的
2:界定通配符的下边界
Vector<? super 类型1> x = new Vector<类型2>();
类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的父类
Vector<? super Integer> x = new Vector<Number>();//这是正确的
Vector<? super Integer> x = new Vector<Byte>();//这是错误的
3:泛型不存在多态
首先回顾一下java的多态
//java的多态回顾
public class Animal { } class Dog extends Animal{ } class Test1 {
public static void main(String[] args) {
//【1】多态 父类引用指向子类对象
Animal animal=new Dog();
add(new Dog());
}
//【2】形参使用多态
public static void add(Animal animal){ }
//【3】返回值类型使用多态
public static Animal get(){
return new Dog();
}
}
泛型不存在多态的示例代码
//泛型类
class App<T>{}
class Test2{
public static void main(String[] args) {
//【1】泛型不存在多态 ,因此错误
//App<Animal> app=new App<Dog>();
App<Animal> app=new App<Animal>(); //【2】当形参规定什么泛型时,传递的实参必须是什么泛型,不存在多态
//add(new App<Dog>());
}
//形参使用多态
public static void add(App<Animal> app){} //【3】返回值类型的多态,也不正确
public static App<Animal> get(){
//return new App<Dog>();返回值类型不存在多态
//return (App<Animal>)(new App<Dog>());强制类型转化也不对
return null;
}
}
4:泛型的通配符:? extends super
[1]通过通配符号,可以实现类似多态的功能
(1)?号的使用 声明类型|声明方法 时使用。不能声明类和使用泛型时使用。
?号可以接受所有类型,只能接收和输出,不能修改
//?的使用
//【1】声明类泛型时不能使用
//【2】声明方法参数时泛型可以使用?号
//【3】声明返回值类型时泛型可以使用?号
//【4】具体使用泛型时不能使用?号,要把?号确定成某一类型 //【1】class Student<?>{}声明类时不能使用
class Student2<T>{
T score;
public static void add(Student2<?> stu){}//【2】声明方法参数时使用?号
//【3】声明返回值类型时可以使用?号
public static Student2<?> get(){
return new Student2<Integer>();
}
} class Test3{
public static void main(String[] args) {
Student2<?> student=new Student2<String>();
//student.add(new Student2<?>());//【4】使用时不能使用?号
student.add(new Student2<Integer>() );//使用时要把?号确定成指定的类型
}
}
(2)? extends V 上限 所使用的泛型必须<=V 必须是V的子类或本身
(3)? super V 下限 所使用的泛型必须>=V 必须是V的超类或本身
//extends super使用
class Student2<T>{
T score; public static void test1(Student2<? extends Animal> st){}
public static void test2(Student2<? super Animal> st){} //annimal是dog的父类
public static void main(String[] args) {
test1(new Student2<Dog>());
//test1(new Student2<Object>());object是Animal的超类,超过上限,报错 test2(new Student2<Object>());
//test2(new Student2<Dog>());dog是Animal的子类,不在下限范围内,报错
}
}
5:泛型的嵌套
public class Bjsxt<T> {
T pe;
}
class Person<T>{
T socre;
}
class Test5{
public static void main(String[] args) {
//泛型的嵌套
Bjsxt<Person<String>> bjsxt=new Bjsxt<Person<String>>();
//从外到内拆分
Person<String> pe=bjsxt.pe;
String socreString=pe.socre;
}
}
6:泛型和数组
(1)没有泛型数组,不能创建泛型数组
(2)可以只有声明,可以使用?
package com.bjsxt.shangxiaofei; public class Array {
public static void main(String[] args) {
Integer[] arr=new Integer[30];//声明一个数组
//Student<String>[] sts=new Student<String>[10];没有泛型数组,但可以声明
Student<String>[] sts=new Student[10]; //可以声明,但并没有什么实际意义
Student<?>[] stss=new Student[10]; MyArrayList<String> mList=new MyArrayList<String>();
mList.add(0, "尚晓飞");
//mList.add(1, new Student());泛型规定是String,也就是说数组里只能存放String
String nameString=mList.get(0);
String[] strs=mList.getAll();
System.out.println("Array.main()"+nameString);
}
} //泛型与数组的应用。巧妙在于将一个object数组,固定存放String的值
class MyArrayList<E>{
//声明一个object数组
Object[] objs=new Object[30]; //给数组添加一个值
public void add(int idx, E e){
objs[idx]=e;
}
//获取数组
public E[] getAll(){
return (E[])objs;
}
//获取某个下标的值
public E get(int idx){
return (E)objs[idx];
} }
7:jdk1.7对泛型的修改
//jdk1.7后对泛型的修改
//只在声明时用一次泛型,创建和使用时不需要,只需要加上<>
List<String> ad=new ArrayList<String>();//1.7以前使用泛型
//List<String> ad2=new ArrayList<>();//1.7以后只需要声明一次 使用和创建时不需要指定类型
asdf
java泛型学习(2)的更多相关文章
- Java泛型学习笔记 - (七)浅析泛型中通配符的使用
一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List< ...
- Java泛型学习笔记--Java泛型和C#泛型比较学习(一)
总结Java的泛型前,先简单的介绍下C#的泛型,通过对比,比较学习Java泛型的目的和设计意图.C#泛型是C#语言2.0和通用语言运行时(CLR)同时支持的一个特性(这一点是导致C#泛型和Java泛型 ...
- Java泛型学习---第二篇
泛型学习第一篇 1.泛型之擦拭法 泛型是一种类似"模板代码"的技术,不同语言的泛型实现方式不一定相同. Java语言的泛型实现方式是擦拭法(Type Erasure). 所谓擦拭法 ...
- java泛型学习(1)
java泛型(Generices Type) --->概念:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和 ...
- Java泛型学习一
Java泛型 所谓泛型,就是变量类型的参数化.泛型是java1.5中引入的一个重要特征,通过引入泛型,可以使编译时类型安全,运行时更少抛出ClassCastException的可能.一提到参数化,最熟 ...
- Java 泛型学习总结
前言 Java 5 添加了泛型,提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,可以为以前处理通用对象的类和方法,指定具体的对象类型.听起来有点抽象, ...
- java 泛型学习随笔
对于java 泛型 编译时处理,运行时擦除的特点理解 对于编译时处理 在使用泛型相关的类或方法时,如果声明时的类型和具体使用时的类型不一致则直接会编译不通过 对于运行时擦除 当在运行时对两个相同类型但 ...
- Java泛型学习笔记 - (六)泛型的继承
在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: Object obj = new Integer(10); 这其实就是面向对象编程中的is ...
- java 泛型学习
http://blog.csdn.net/archie2010/article/details/6232228 学习集合框架的时候经常用hasmap<Integer,Integer>就是泛 ...
随机推荐
- 关于网站的SYN_RECV(SYN_RECEIVED)***的防范措施
关于网站的SYN_RECV(SYN_RECEIVED)***的防范措施 一.总结 一句话总结:SYN ***是最常见又最容易被利用的一种***手法.相信很多人还记得2000年YAHOO网站遭受的*** ...
- 微信公众号菜单添加小程序,miniprogram,pagepath参数详解,php开发公众号
随着微信小程序功能的开发, 已经可以跟公众号打通了, 主要有两种方式: 1) 在公众号文章中插入小程序 2) 在公众号菜单中添加小程序 第一种方式, 子恒老师在前面的课程已经详细介绍过, 今天来讲第二 ...
- C#开发框架学习
C# 开源框架(整理) Json.NET http://json.codeplex.com/ Json.Net 是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用J ...
- Professional layer CodeForces - 1103D (状压,gcd)
大意: 给定$n$元素序列$a$, 现在想要让$gcd(a_1,a_2,...,a_n)=1$. 对于每个$a_i$可以除以一个不超过$k$的因子, 代价为$e_i$, 假设一共选择了$x$个元素去除 ...
- ZOJ 2770 差分约束+SPFA
Burn the Linked Camp Time Limit: 2 Seconds Memory Limit: 65536 KB It is well known that, in the ...
- nyoj 1238(BFSor最短路)
最少换乘 时间限制:2000 ms | 内存限制:65535 KB 难度:3 描述 欧洲某城是一个著名的旅游胜地,每年都有成千上万的人前来观光旅行.Dr. Kong决定利用暑假好好游览一番.. ...
- 访问IIS元数据库失败的解决方法
这两天在调试一个Asp.net程序时,出现了“访问IIS元数据库失败”的错误信息,最后终于摸索出了解决问题的方法.公布如下: 1.依次点击“开始”-“运行”. 2.在“运行”栏内输入 “C:\WIND ...
- Awk 从入门到放弃(1)–学习笔记
参考:朱双印博客 1. 将test文件中的内容打印出来:vmuser@vmuser-virtual-machine:~/panzidong/awk$ echo ddd > testvmuser@ ...
- 快速切题 sgu105. Div 3 数学归纳 数位+整除 难度:0
105. Div 3 time limit per test: 0.25 sec. memory limit per test: 4096 KB There is sequence 1, 12, 12 ...
- glusterfs分布式存储
一,分布式文件系统理论基础 1.1 分布式文件系统出现 计算机通过文件系统管理,存储数据,而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长,单纯通过增加硬盘个数来扩展计算机文件系统的存储容量 ...