Jadual Kandungan
一、泛型简介
二、为什么需要泛型
2.1、编译期对数据类型进行检测
2.2强制转换是自动的
运行结果:
三、深入泛型
3.1 、有两个类,我们需要打印他们的成员变量
3.2、重构
3.3使用泛型重构
下面解释一下上面的泛型语法:
Rumah Java javaTutorial java之泛型

java之泛型

Feb 24, 2017 am 09:56 AM
java Generik

一、泛型简介

  泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
  在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
  泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

二、为什么需要泛型

2.1、编译期对数据类型进行检测

首先我们看一个案例,向一个ArrayList中添加字符串,“不小心”添加了整数,如下面代码,
并没有错误:

这里写图片描述

但是执行时,会报错:“java.lang.classCastException”

这里写图片描述

因为ArrayList中维护的是一个Object数组, private transient Object[] elementData;
, 使用get()返回的是一个Object对象, 需要强制转换,但是中间混杂一个Integer数值, 导致强制转换失败。这个错误就是由于Object的任意化导致的。
如果能在编译阶段就发现数据类型有错, 那么就很方便,泛型就满足了这个要求:我将这个程序修改一下,ArrayList使用泛型:会发现编译阶段就报错了.
这里写图片描述

2.2强制转换是自动的

不使用泛型:

package com.chb.fanxing;public class NoGen {    
private Object ob;    
public NoGen(Object ob) {        
this.ob = ob;
    }
    getter setter...    
    private void showType() {
        System.out.println("数据的实际类型是:" + ob.getClass().getName());
    }    public static void main(String[] args) {
        NoGen ngInt = new NoGen(88);
        ngInt.showType();        int i = (int)ngInt.getOb();
        System.out.println("value = " + i);
        System.out.println("---------------");

        NoGen ngStr = new NoGen("88");
        ngStr.showType();
        String str = (String)ngStr.getOb();
        System.out.println("value = " + str);   
    }
}
Salin selepas log masuk

使用泛型:

package com.chb.fanxing;public class Gen<T> {    
private T ob;    
public Gen(T ob) {        
this.ob = ob;
    }
    getter setter...    
    private void showType() {
        System.out.println("T的实际类型:"+ob.getClass().getName());
    }    public static void main(String[] args) {        //定义一个Integer版本
        Gen<Integer> genInt = new Gen<Integer>(88);
        genInt.showType();        int i = genInt.getOb();//此处不用强制转换
        System.out.println("value = " + i);
        System.out.println("----------------------");

        Gen<String> genStr = new Gen<String>("88");
        genStr.showType();
        String str = genStr.getOb();
        System.out.println("value = "+str); 
    }
}
Salin selepas log masuk

运行结果:

两个例子的运行结果是一致的

数据的实际类型是:java.lang.Integervalue = 88
---------------数据的实际类型是:java.lang.String
value = 88
Salin selepas log masuk
Salin selepas log masuk

对比两个例子会发现:

  • 使用泛型,强制转换时自动进行的:

int i = genInt.getOb();//此处不用强制转换
Salin selepas log masuk
Salin selepas log masuk
  • 而不使用泛型,必须要进行手动强制转化

int i = (int)ngInt.getOb();
Salin selepas log masuk
Salin selepas log masuk

三、深入泛型

3.1 、有两个类,我们需要打印他们的成员变量

class StringDemo {    
private String s;    
public StringDemo (String s) {        
this.s = s;
    }
    setter geter....
}
class DoubleDemo{    
private Double d;    
public DoubleDemo(Double d) {        
this.d = d;
    }
    setter getter...
}
Salin selepas log masuk
Salin selepas log masuk

3.2、重构

仔细观察两个类功能基本一致,只是数据类型不一样,考虑到重构,因为Object是所有类的基类,所以可以使用Object作为成员变量,这样代码就可以通用了。重构代码如下:

class ObjectDemo{
    private Object ob;    
    public ObjectDemo(Object ob){        
    this.ob = ob;
    }
    setter getter...
}
Salin selepas log masuk
Salin selepas log masuk

ObjectDemo测试:

public static void ObjectDemoTest(){
        ObjectDemo strOD = new ObjectDemo("123");
        ObjectDemo dOD = new ObjectDemo(new Double(23));
        ObjectDemo od = new ObjectDemo(new Object());
        System.out.println((String)strOD.getOb());
        System.out.println((Double)dOD.getOb());
        System.out.println(od.getOb());
    }
Salin selepas log masuk
Salin selepas log masuk

运行结果:
这里写图片描述

3.3使用泛型重构

发现上面的ObjectDemoTest() 中必须要使用强制转换,这比较麻烦,我们还必须事先知道要转换的数据类型,才能进行正确的转换,否则,会出现错误, 业务编译时没有问题,但是一运行,会出现”classCastException”。所以我们需要不用自己进行强制转换,这是泛型就尤为重要。

class GenDemo<T>{    
private T t;    
public GenDemo(T t) {        
this.t = t;
    } 
    public void setT(T t) {        
    this.t = t;
    }    
    public T getT() {        
    return t;
    }
}
Salin selepas log masuk

测试:省去了手动进行强制转换

public static void GenTest() {
        GenDemo<String> strOD = new GenDemo<String>("123");
        GenDemo<Double> dOD = new GenDemo<Double>(new Double(23));
        GenDemo<Object> od = new GenDemo<Object>(new Object());
        System.out.println(strOD.getT());
        System.out.println(dOD.getT());
        System.out.println(od.getT());
}
Salin selepas log masuk
Salin selepas log masuk

下面解释一下上面的泛型语法:

使用表示一个类型持有者名称, 相当于一个形参,数据的类型是有实际传入的数据的类型决定,然后T作为成员、参数、方法的返回值的类型。
T仅仅是一个名字,可以随意取的。
class GenDemo , T没有进行任何限制, 实际相当于 Object,
等同于 class GenDemo。
与Object相比,使用泛型所定义的类,在定义和声明,可以使用<实际类型>来制定真实的数据类型,如:

GenDemo dOD = new GenDemo(new Double(23));
也可以不指定,那么就需要进行强制转换。

下文我们将继续java的泛型
限制泛型
多接口限制
通配符泛型

一、泛型简介

  泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
  在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
  泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

二、为什么需要泛型

2.1、编译期对数据类型进行检测

首先我们看一个案例,向一个ArrayList中添加字符串,“不小心”添加了整数,如下面代码,
并没有错误:

这里写图片描述

但是执行时,会报错:“java.lang.classCastException”

这里写图片描述

因为ArrayList中维护的是一个Object数组, private transient Object[] elementData;
, 使用get()返回的是一个Object对象, 需要强制转换,但是中间混杂一个Integer数值, 导致强制转换失败。这个错误就是由于Object的任意化导致的。
如果能在编译阶段就发现数据类型有错, 那么就很方便,泛型就满足了这个要求:我将这个程序修改一下,ArrayList使用泛型:会发现编译阶段就报错了.
这里写图片描述

2.2强制转换是自动的

不使用泛型:

package com.chb.fanxing;public class NoGen {    
private Object ob;    
public NoGen(Object ob) {        
this.ob = ob;
    }
    getter setter...    private void showType() {
        System.out.println("数据的实际类型是:" + ob.getClass().getName());
    }    public static void main(String[] args) {
        NoGen ngInt = new NoGen(88);
        ngInt.showType();        int i = (int)ngInt.getOb();
        System.out.println("value = " + i);
        System.out.println("---------------");

        NoGen ngStr = new NoGen("88");
        ngStr.showType();
        String str = (String)ngStr.getOb();
        System.out.println("value = " + str);   
    }
}
Salin selepas log masuk

使用泛型:

package com.chb.fanxing;public class Gen<T> {    
private T ob;    
public Gen(T ob) {        
this.ob = ob;
    }
    getter setter...    private void showType() {
        System.out.println("T的实际类型:"+ob.getClass().getName());
    }    public static void main(String[] args) {        //定义一个Integer版本
        Gen<Integer> genInt = new Gen<Integer>(88);
        genInt.showType();        int i = genInt.getOb();//此处不用强制转换
        System.out.println("value = " + i);
        System.out.println("----------------------");

        Gen<String> genStr = new Gen<String>("88");
        genStr.showType();
        String str = genStr.getOb();
        System.out.println("value = "+str); 
    }
}
Salin selepas log masuk

运行结果:

两个例子的运行结果是一致的

数据的实际类型是:java.lang.Integervalue = 88
---------------数据的实际类型是:java.lang.String
value = 88
Salin selepas log masuk
Salin selepas log masuk

对比两个例子会发现:

  • 使用泛型,强制转换时自动进行的:

int i = genInt.getOb();//此处不用强制转换
Salin selepas log masuk
Salin selepas log masuk
  • 而不使用泛型,必须要进行手动强制转化

int i = (int)ngInt.getOb();
Salin selepas log masuk
Salin selepas log masuk

三、深入泛型

3.1 、有两个类,我们需要打印他们的成员变量

class StringDemo {    
private String s;    
public StringDemo (String s) {        
this.s = s;
    }
    setter geter....
}
class DoubleDemo{    
private Double d;    
public DoubleDemo(Double d) {        
this.d = d;
    }
    setter getter...
}
Salin selepas log masuk
Salin selepas log masuk

3.2、重构

仔细观察两个类功能基本一致,只是数据类型不一样,考虑到重构,因为Object是所有类的基类,所以可以使用Object作为成员变量,这样代码就可以通用了。重构代码如下:

class ObjectDemo{
    private Object ob;    
    public ObjectDemo(Object ob){        
    this.ob = ob;
    }
    setter getter...
}
Salin selepas log masuk
Salin selepas log masuk

ObjectDemo测试:

public static void ObjectDemoTest(){
        ObjectDemo strOD = new ObjectDemo("123");
        ObjectDemo dOD = new ObjectDemo(new Double(23));
        ObjectDemo od = new ObjectDemo(new Object());
        System.out.println((String)strOD.getOb());
        System.out.println((Double)dOD.getOb());
        System.out.println(od.getOb());
    }
Salin selepas log masuk
Salin selepas log masuk

运行结果:
这里写图片描述

3.3使用泛型重构

发现上面的ObjectDemoTest() 中必须要使用强制转换,这比较麻烦,我们还必须事先知道要转换的数据类型,才能进行正确的转换,否则,会出现错误, 业务编译时没有问题,但是一运行,会出现”classCastException”。所以我们需要不用自己进行强制转换,这是泛型就尤为重要。

class GenDemo<T>{    private T t;    public GenDemo(T t) {        this.t = t;
    } 
    public void setT(T t) {        this.t = t;
    }    public T getT() {        return t;
    }
}
Salin selepas log masuk

测试:省去了手动进行强制转换

public static void GenTest() {
        GenDemo<String> strOD = new GenDemo<String>("123");
        GenDemo<Double> dOD = new GenDemo<Double>(new Double(23));
        GenDemo<Object> od = new GenDemo<Object>(new Object());
        System.out.println(strOD.getT());
        System.out.println(dOD.getT());
        System.out.println(od.getT());
}
Salin selepas log masuk
Salin selepas log masuk

下面解释一下上面的泛型语法:

使用表示一个类型持有者名称, 相当于一个形参,数据的类型是有实际传入的数据的类型决定,然后T作为成员、参数、方法的返回值的类型。
T仅仅是一个名字,可以随意取的。
class GenDemo , T没有进行任何限制, 实际相当于 Object,  
等同于 class GenDemo。
与Object相比,使用泛型所定义的类,在定义和声明,可以使用<实际类型>来制定真实的数据类型,如:

GenDemo dOD = new GenDemo(new Double(23));
也可以不指定,那么就需要进行强制转换。

 以上就是java之泛型的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Akar Kuasa Dua di Jawa Akar Kuasa Dua di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Square Root di Java. Di sini kita membincangkan cara Square Root berfungsi di Java dengan contoh dan pelaksanaan kodnya masing-masing.

Nombor Sempurna di Jawa Nombor Sempurna di Jawa Aug 30, 2024 pm 04:28 PM

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Nombor Armstrong di Jawa Nombor Armstrong di Jawa Aug 30, 2024 pm 04:26 PM

Panduan untuk Nombor Armstrong di Jawa. Di sini kita membincangkan pengenalan kepada nombor Armstrong di java bersama-sama dengan beberapa kod.

Penjana Nombor Rawak di Jawa Penjana Nombor Rawak di Jawa Aug 30, 2024 pm 04:27 PM

Panduan untuk Penjana Nombor Rawak di Jawa. Di sini kita membincangkan Fungsi dalam Java dengan contoh dan dua Penjana berbeza dengan contoh lain.

Weka di Jawa Weka di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Nombor Smith di Jawa Nombor Smith di Jawa Aug 30, 2024 pm 04:28 PM

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Soalan Temuduga Java Spring Soalan Temuduga Java Spring Aug 30, 2024 pm 04:29 PM

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Cuti atau kembali dari Java 8 Stream Foreach? Cuti atau kembali dari Java 8 Stream Foreach? Feb 07, 2025 pm 12:09 PM

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

See all articles