黑马程序员之----------Java泛型
来源:互联网 发布:php断点续传 上传 编辑:程序博客网 时间:2024/05/18 17:27
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培
训、.Net培训</a>、期待与您交流! -------
------------------------java泛型笔记--------------------------
1. 泛型在类、接口和方法中定义,在实现和实例化时使用。
/* 泛型就是指在对象建立时,不指定类中属性的具体类型,由外部声明及实例化对象时指定具体类型。
* 其只要原理是在类声明时通过一个标识,表示类中某个属性的类型或者是某个方法的返回值及参数类型。
* 这样在类声明或实例化的时候只要指定好需要的具体类型即可。
* public class <T ,M ....> {
* private T t;
* public T show (){}
* public int show (T t){}
* }
*/
//声明泛型
class Point<T>{//此处可以是任意标识符
private T var;//此变量由外部决定
public T getVar(){//返回值由外部决定
return var;
}
public void setVar(T var){
this.var=var;
}
}
public class GenericsDemmo1 {
public static void main(String [] args){
//里面的var类型为Integer
Point <Integer> pp=new Point<Integer>();
//设置泛型可以保证数据类型的一致接受的都是Integer类型
//设置数字,自动装箱
pp.setVar(30);
//会报错,设置的内容与泛型不一致
//pp.setVar("zhang");
System.out.print(pp.getVar()*2);
}
}
2./* 泛型方法
* 1.定义一个可以接收任意类型的数据
* public <T> T fun(T t){return t};
*/
class Pointer<T> {// 此处可以是任意标识符
private T var;// 此变量由外部决定
public Pointer(T var){//构造函数声明,与类上声明无关
this.var=var;
}
public T getVar() {// 返回值由外部决定
return var;
}
public void setVar(T var) {//设置类型由外部决定
this.var = var;
}
}
public class GenericsDemmo2 {
public static void main(String[] args) {
// 里面的var类型为String
Pointer<String> pp = new Pointer<String>("小白");
Pointer<Integer> pp1 = new Pointer<Integer>(23);
//方法中的两个对象类型必须一致,否则编译错误
//add(pp,pp1);
}
//静态方法书写规范 public static <E> set<E> add(set<E> s1,set<E> s2) ;
public static <T> void add(Pointer<T> PP,Pointer<T> PP1){
//
//System.out.print("名字叫:"+pp.getVar()+pp1);
}
}
3./* 如果在使用类是不指定泛型,默认的为Object.
* 会出现安全隐患
* 通配符<?>表示任意泛型,并且如果使用<?>接受泛型对象时,不能设置被泛型指定的内容
* Info <?> i=new Info<String>();
* 表示接收的泛型类型<?>
* i.setVar("小白")//错误,不能设置
* 但是此时可以设置为null
* i.setVar(null);//可以设置
*/
class Notepad<K,V> {// 此处可以是任意标识符
private K key;// 此变量由外部决定
private V value;
public K getKey() {// 返回值由外部决定
return key;
}
public void setKey(K key) {//设置类型由外部决定
this.key=key;
}
public V getValue() {// 返回值由外部决定
return value;
}
public void setValue(V value) {//设置类型由外部决定
this.value=value;
}
}
public class GenericsDemmo3 {
public static void main(String[] args) {
// 里面的var类型为String
Notepad<String,Integer> pp = new Notepad<String,Integer>();
pp.setKey("小白");
pp.setValue(3);
System.out.print("名字叫:"+pp.getKey()+"现在"+pp.getValue()+"岁");
}
}
4./* 上限和下限
* 上限:表示泛型类型为Person 或者是其子类
* 声明对象:Person <? extend Person> st;
* 定义类:public Person <T extends Person>
*
* 下限:表示泛型类型为Person 或者是其父类或者是Object类
* 声明对象:Person <? super Person> st;
* 定义类:public Person <T extends Person>
*
* 子类可以通过对象的多态性为其父类实例化。但是在泛型中,子类的泛型类型
* 无法使用父类泛型接收。
* Info <String> i=new Info<String>();
* Info <Object> i2=i;//错误,类型不匹配
* 虽然String是Object的子类,但在泛型中,没有此概念。只能用<?>接受
* Info <?> =i;//正确
*
*/
class Info<T extends Number>{
private T var;
public T getVar(){//返回值由外部决定
return var;
}
public void setVar(T var){
this.var=var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemmo4 {
public static void main(String[] args) {
Info <Integer> i=new Info<Integer>();//接收Number的子类
Info <Float> i2=new Info<Float>();//接收Number的子类
i.setVar(23);
i2.setVar(30.f);
fun(i);
fun(i2);
}
//这里设置了接收的范围上限,包括Number及其子类<? extends T>
//集合中存放元素的时候一般使用上限,可以添加父类型的元素,也可以添加子类型的元素,提高了扩展性
public static void fun(Info<? extends Number> temp){
System.out.print(temp+",");
}
}
5./*
* 下限
*/
class Info1<T>{//类型为T(Object)
private T var;
public T getVar(){//返回值由外部决定
return var;
}
public void setVar(T var){
this.var=var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemmo5 {
public static void main(String[] args) {
Info1 <String> i=new Info1<String>();//接收String型
Info1 <Object> i2=new Info1<Object>();//接收Object型
i.setVar("小白");
i2.setVar(new Object());
fun(i);
fun(i2);
}
//这里设置了范围的下限,包括String及其父类Object,<? super T>
//通常对集合中的元素进行取出操作时,可以使用下限,表示取出的元素(父类共性类型)
//也就是说对传进迭代器中的元素,全用父类去接收,以保证全部接受。
public static void fun(Info1<? super String> temp){
System.out.print(temp+",");
}
}
6./*泛型接口
* public interface Info<T>{}
* 两种实现方式
* 1.子类实例化时,指定泛型接口类型
* interface A <T>{
public T getVar();
}
//定义泛型接口的子类,也必须是T
class B <T> implements A <T>{
private T var;
public B(T var){
this.setVar(var);
}
public void setVar(T var){
this.var=var;
}
public T getVar(){
return this.var;
}
}
public class GenericsDemmo6 {
public static void main(String[] args) {
//定义接口的泛型类型
B <String> b=new B<String>("小白");
System.out.print("名字叫:"+b.getVar());
}
}
* 2.继承接口时,直接指定泛型类型
*
*/
interface A <T>{
public T getVar();
}
//定义泛型接口的子类,也必须是T
class B implements A <String>{
private String var;
public B(String var){
this.setVar(var);
}
public void setVar(String var){
this.var=var;
}
public String getVar(){
return this.var;
}
}
public class GenericsDemmo6 {
public static void main(String[] args) {
//实例化子类的时候,不能指定泛型
B b=new B("小白");
System.out.print("名字叫:"+b.getVar());
}
}
7. 注意:
定义类或接口时,使用"<E extends Fruit>"这种形式,之后就可以在类中对E进行操作。
定义方法所接收的参数时,使用"List<? extends Fruit>"这种形式,就可以接收这个范围的List做参数。
实例化时,不能使用问号这种形式来指定泛型——不能new List<? extends Apple>();
继承或实现时,也不能使用问号这种形式来指定泛型——不能public interface MyList extends List
<? extends Apple>
不能实例化泛型类型的数组:new List<String>[3]是不合法的。
但是在可以确定类型的情况下,将Object数组强制转换成泛型数组是合法的,
例如ArrayList的源码:return (T[]) Arrays.copyOf(elementData, size, a.getClass());
8. 泛型的继承原则:
1,相同类型参数的泛型类的关系取决于泛型类自身的继承体系结构。即List<String>是Collection <String>的子类型,List<String>可以替换Collection<String>。这种情况也适用于带有上下界的类型声明。
2,当泛型类的类型声明中使用了通配符的时候, 其子类型可以在两个维度上分别展开。如对Collection<? extends Number>来说,其子类型可以在Collection这个维度上展开,即List<? extends Number>和Set<? extends Number>等;也可以在Number这个层次上展开,即Collection<Double>和 Collection<Integer>等。如此循环下去,ArrayList<Long>和 HashSet<Double>等也都算是Collection<? extends Number>的子类型。
3,如果泛型类中包含多个类型参数,则对于每个类型参数分别应用上面的规则。
9. 泛型的定义原则:
1,泛型类与一般的Java类基本相同,只是在类和接口定义上多出来了用<>声明的类型参数。
2,一个类可以有多个类型参数,如 MyClass<X, Y, Z>。
3,每个类型参数在声明的时候可以指定上界。
4,所声明的类型参数在Java类中可以像一般的类型一样作为方法的参数和返回值,或是作为域和局部变量的类型。
5,由于类型擦除机制,类型参数并不能用来创建对象或是作为静态变量的类型。
--------------------------------------------------------------------------------
import java.util.ArrayList;
import java.util.List;
class AbstractTester {
}
class Fruit {
}
class Apple extends Fruit {
}
class GenericTester extends AbstractTester {
public void test1() {
List<Apple> appleList = new ArrayList<Apple>();
appleList.add(new Apple()); // 先定义List<Apple>,填入元素,限定Apple类型
Fruit fruit = Basket.getFruit(appleList); // List<Apple>类型符合List<? extends Fruit>的要求
}
public void test2() {
List<Fruit> fruitList = new ArrayList<Fruit>();// 先定义List<Fruit>,填入元素,限定Fruit类型
Basket.addApple(fruitList, new Apple()); // List<Fruit>符合List<? super Apple>的要求
}
}
class Basket {
// 从泛型化的list中取出Fruit,里面的元素一定是Fruit的子类,所以都可以当作Fruit返回
public static Fruit getFruit(List<? extends Fruit> list) {
return list.get(0);
}
// 将Apple放入泛型化的list(这个list可以接收的类型是Apple的父类,所以一定可以接收apple或apple的子类)
public static void addApple(List<? super Apple> list, Apple apple) {
list.add(apple);
}
}
public class GenericCompileTester {
public void addInteger1(List<?> list) {
list.add(1); // 编译错误,因为问号代表“编译时不确定,但运行时确定”的类型,Integer不一定符合要求,其实这里相当于<?
// extends Object>
}
public void addInteger2(List<Object> list) {
list.add(1); // 编译通过,因为编译时和运行时都确定了是Object类型,Integer肯定符合要求
}
public void test() {
List<String> list = new ArrayList<String>();
addInteger2(list); // 编译错误,因为List<String>不能当作List<Object>传入,否则数字1将被当作String添加,类型将不再安全
}
public void test3() {
List<? extends Fruit> fruitList = new ArrayList<Apple>();
fruitList.add(new Apple()); // 编译错误,编译器无法确定List允许的是Fruit的具体哪一个子类
fruitList.add(new Fruit()); // 编译错误,编译器无法确定List允许的是Fruit的具体哪一个子类
}
public void test4() {
List<? super Apple> fruitList = new ArrayList<Fruit>();
fruitList.add(new Apple()); // 编译通过,Apple和Apple的子类都可以保证符合条件要求
fruitList.add(new Fruit()); // 编译错误,编译器无法确定List允许的是Apple的具体那个级别的父类或接口
}
}
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培
训、.Net培训</a>、期待与您交流! -------
- 黑马程序员之----------Java泛型
- 黑马程序员java笔记之五-----泛型
- 黑马程序员java自学总结之--泛型
- 【黑马程序员】黑马入学准备篇:Java高新技术之 泛型
- 黑马程序员之了解java
- 黑马程序员--JAVA之反射
- 黑马程序员之java多线程
- 黑马程序员之-------------java多线程
- 黑马程序员 java之异常
- 黑马程序员 java之反射
- 黑马程序员---Java之异常
- 黑马程序员---Java之IO
- 黑马程序员---Java之反射
- 黑马程序员-Java之LinkedList
- 黑马程序员-Java之HashSet
- 黑马程序员-java之反射
- 黑马程序员java之IO_1
- 黑马程序员java之IO_2
- 2014-8-28 Android 笔记
- 黑马程序员之---———Java异常机制
- 黑马程序员之-------java集合笔记
- Direct2D 1.1 开发笔记 特效篇(一) 使用D2D特效
- 宏
- 黑马程序员之----------Java泛型
- 黑马程序员之-------------java多线程
- Using Resolve In AngularJS Routes
- android通过socket实现发送邮件
- 手游那些年遇到的9个坑
- [Leetcode]Set Matrix Zeroes
- Convert Sorted List to Binary Search Tree
- 对不包含括号的算式字符串进行四则运算
- opencv resize和Matlab imresize结果不一致