第二十一章 泛型(generic)

2024-01-24 09:58

本文主要是介绍第二十一章 泛型(generic),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第二十一章 泛型(generic)
(1)引言
     泛型:是指参数化类型的能力。
     例如:有这样一个类:这是一个比较简单并且是很常用的带有泛型的方法。


     package com.lidd.generic;


     public class GenericTestSecond {

public <T>void one(T t){


}


      }


      下面是几个类,分别是一般类、抽象类、接口(接口也是特殊的类)。


      package com.lidd.generic;


      public class A {


      }


      package com.lidd.generic;


      public abstract class B {


      }


      package com.lidd.generic;


      public interface C {




     }


     接下里是主函数:
     package com.lidd.generic;
     public class MainTest {
public static void main(String[] args) {

GenericTestSecond o = new GenericTestSecond();
o.one(new C(){});   //C
o.one(new A());     // A
o.one(new B(){});   // B
o.one("bbbb");      // String
o.one(1);           // Integer

}


    }


    可以看到main方法中实例化了一个GenericTestSecond对象。方法one中传的参数类型可以是C、A、B、String、Integer等等,也就是说方法one中的泛型并不是指代某一种具体的类型
    而实在具体类型的基础上又进行了一层参数化。这就是定义中所说的参数化类型的能力。


   (2)泛型的优点。
        在jdk 1.5之前
package java,lang;
public interface Comparable{

public int compareTo(Object o);
}
在jdk1.5开始及其以后
package java.lang;
public interface Comparable<T>{
  public int compareTo(T t);
}




     1、泛型使得程序更加可靠。


     Comparable c = new Date();
     System.out.println(c.compareTo("red"));


     Comparable<Date> c = new Date();
     System.out.println(c.compareTo("red"));


     62 中一个时间和一个String字符串去做比较,但是在编译期不会有任何问题。但是在运行时会报错。
     65 中在编译的时候就会报错,因为Comparable中使用了泛型,并且在64行指定为Date类型。
     注意:
     泛型类型必须是应用类型,不能用像int double或char这样的基本类型来替换泛型类型。例如下面的语句是错误的:
     ArrayList<int> list = new ArrayList<int>();
     必须是ArrayList<Integer> list = new ArrayList<Integer>();
     2、无需类型转换。
     例如:
     ArrayList<String> strList = new ArrayList<String>();
     strList.add("one");
     strList.add("two");
     String str = strList.get(0);
     91 行不需要这样 String str = (String)strList.get(0);
     (3) 泛型的几种常见形式。
     1、泛型类(抽象类):
     public class GenericStack<E>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

public int getSize(){


return list.size();
}
public E peek(){
return list.get(getSize()-1);

}
public void push(E e){
list.add(e);

}
public E pop(){

E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}


public boolean isEmpty(){

return list.isEmpty();

}

  
     }
     或者是:


      public class GenericStack<E extends A>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

public int getSize(){


return list.size();
}
public E peek(){
return list.get(getSize()-1);

}
public void push(E e){
list.add(e);

}
public E pop(){

E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}


public boolean isEmpty(){

return list.isEmpty();

}

  
     }
    


     其中A为一个类。


      2、泛型接口:
      public interface Comparable<T>{
public int compareTo(T t);
      
      }
      或者是:
      public interface Comparable<T extends A>{
 public int compareTo(T t);
      
      }
   


      其中A为一个类。


      3、泛型方法:
      public class MyTest{
      
        // 注意<T>在方法的返回值类型之前
public <T>void one(T t){

}
      
      }


      或者:
      public class MyTest{
      
        // 注意<T>在方法的返回值类型之前
public <T extends A>void one(T t){

}
      
      }
  


      其中A为一个类。

     (4)通配泛型:
     以95行的类做前置准备。
     为啥需要通配泛型?
     pulic class demo1{
     
     public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
System.out.println("The max number is"+max(stack));
     
     }
    public static double max(GenericStack<Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
    
    }
     
  }


   其中208会出现编译错误,虽然Integer是Number的子类,但是GenericStack<Integer> 不是GenericStack<Number>的子类.
   这个时候通配泛型登场了。
   上面的代码稍加改动就可以消除208的编译错误。
   修改:211-221
   public static double max(GenericStack<? extends Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
    
    } 
    1、通配泛型的分类:
    第一类:?(非受限通配) 相当于 ?extends Object。
    例子:
    pulic class demo2{
     
     public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
print(stack);
     
     }
    public static double print(GenericStack<?> stack){


while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
    
     }
     
   }
   注意253行-259行
   虽然GenericStack<?>相当于GenericStack<? extends Object>,但是不能是
     public static double print(GenericStack<Object> stack){


while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
    
     } 


     否则的话250行编译不能通过。这是因为GenericStack<Integer> 不是GenericStack<Object>的子类。此处有体现的通配泛型的
     必要性。




    第二类:?extends T (受限通配) // 其中的T是某个泛型类型。
参考228-239行。




    第三类:?super T (下限通配)// 其中的T是某个泛型类型。


    public class demo3{

public static void main(String[] args){

GenericStack<String> stack1 = new GenericStack<String>();
GenericStack<Object> stack2 = new GenericStack<Object>();
stack1.add("java");
stack1.add("love");
stack2.add(1);
stack2.add(2);


add(stack1,stack2);

}
public static <T>void add(GenericSatck<T> stackTo,GenericStack<? super T> destStack){

while(!stackTo.isEmpty()){

destStack.push(stack1.pop());

}



}
    
    }


    296行如果使用<T>代替<? super T> ,那么293就会编译异常。


    (5)泛型消除:
    泛型是使用一种称为类型消除的方法来实现的。编译器使用泛型类型信息来编译代码,
    但是随后就会消除它。因此,泛型信息在运行时是不可用的。
    
//===========================================读java语言程序设计进阶篇笔记====================================================














这篇关于第二十一章 泛型(generic)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/639318

相关文章

Java泛型类型解析

解析泛型类型 获取字段泛型类型 **java.lang.reflect.Field#getGenericType**: 作用:返回字段的泛型类型。返回类型:Type。如果字段是一个泛型类型,这个方法将返回一个表示这个泛型类型的 Type 对象,比如 ParameterizedType,TypeVariable 等等。如果字段不是泛型类型,这个方法将返回字段的具体类型,即 Class 对象。示例

【数据结构】--初识泛型

1. 包装类 在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。 1.1 基本数据类型和对应的包装类 除了 Integer 和 Character, 其余基本类型的包装类都是首字母大写。 1.2 (自动)装箱和(自动)拆箱 装箱(装包): 把 基本数据类型 变为 包装类类型 的过程 叫做装箱。 反汇编指

泛型参Class、Class、Class的对比区别

1.原文链接 泛型参Class、Class、Class的对比区别 https://blog.csdn.net/jitianxia68/article/details/73610606 <? extends T>和<? super T> https://www.cnblogs.com/drizzlewithwind/p/6100164.html   2.具体内容: 泛型参数Class、

Java|泛型的使用

文章目录 概述泛型的基本概念泛型类示例 泛型方法示例 泛型接口示例 泛型的类型参数约束示例 通配符(Wildcard)上界通配符(`? extends T`)下界通配符(`? super T`) 泛型的类型擦除类型擦除的影响 泛型中的常见限制泛型的优点 总结 概述 泛型(Generic)是 Java 5 引入的一项特性,它允许类、接口和方法可以处理任何类型的数据,而不必指定具体

hibernate泛型Dao,让持久层简洁起来

【前言】hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据库。同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么我们在项目中如何灵活应用hibernate,也会给项目维护以及项目开发带来便利,下面我将展示我们项目中是如何来对hibernate进行应用和操作。 【目录】              -

第二十一章 rust与动静态库的结合使用

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust与动静态库的结合使用 目录 注意一、前言二、库生成三、库使用四、总结 一、前言 rust中多了很多类型的库,比如前面章节中我们提到基本的bin与lib这两种crate类型库。 如果你在命令行执行下列语句: rustc --help 那么你将能找到这样的内容: --crate-type [bin|li

dart 中的 泛型 怎么写??

import 'package:flutterdemo/bean/MyUser.dart';class BaseResp<T> {int code;String str;T data;BaseResp({this.code, this.str, this.data});BaseResp.fromJson(Map<String, dynamic> jsonStr) {code = jsonStr['

泛型第四课,自定义实现迭代器、深入迭代器、迭代器原理,面向对象

package com.pkushutong.genericity4;import java.util.Iterator;/*** 简化迭代器原理* @author dell**/public class Array2 implements java.lang.Iterable<String>{private String[] elem = {"a","b","c","d","e","f","g

泛型第三课,自定义泛型、无多态、通配符、无泛型数组

泛型没有多态 package com.pkushutong.genericity4;/*** 多态的两种形式* 注:泛型没有多态* @author dell**/public class Test01 {public static void main(String[] args) {Fruit f = new Fruit();test(new Apple());}//形参使用多态publi

泛型第二课,派生子类、属性类型、方法重写、泛型擦除

子类(实现类) 子类与父类|接口一样使用泛型子类指定具体的类型子类与父类|接口 同时擦除类型子类泛型,父类|接口 擦除错误:不能子类擦除,父类|接口泛型 package com.pkushutong.genericity3;/*** 父类为泛型类* 1、属性* 2、方法* * 要么同时擦除,要么子类大于等于父类的类型* 不能子类擦除,父类泛型* 1、属性类型* 父类中,随父类型定