您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java进阶知识,轻松理解Java泛型

时间:2020-08-20 10:06:45  来源:  作者:

在学习泛型之前我们先回顾下JAVA的数据类型以及涉及到的一些概念。

Java数据类型

Java的两大数据类型分为基础类型和引用类型。基本类型的数值不是对象,不能调用对象的toString()、hashCode()、getClass()、equals()等方法。

Java进阶知识,轻松理解Java泛型

 

自动装箱

把基本类型用它们对应的引用类型包装起来,使它们具有对象的特质,可以调用toString()、hashCode()、getClass()、equals()等方法。

例如:

//自动装箱
Integer i=1;

而实际上编译器会调用static Integer valueOf(int i)这个方法,返回一个表示指定int值的Integer对象。Integer i=1; ->. Integer i=Integer.valueOf(1);

拆箱

跟自动装箱的方向相反,将引用类型转换为基本类型。

//拆箱
int i = new Integer(1);

自动装箱和拆箱是由编译器来完成的,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

假如我们定义一个类来表示坐标,要求类中基础类型可以为整数 、小数、字符串,例如:

Object x=116,y=54;
Object x=116.92,y=54.31;
Object x="经度116.92",y="纬度54.31";

我们知道,基本数据类型可以自动装箱,被转换成对应的包装类。Object 是所有类的祖先类,任何一个类的实例都可以向上转型为 Object 类型,例如:

int -> Integer -> Object
double -> Double -> Object
String -> Object

泛型的使用

Java进阶知识,轻松理解Java泛型

 

如果要取出坐标值就需要向下转型,向下转型存在着风险,而且编译期间不容易发现,只有在运行期间才会抛出异常,所以要尽量避免使用向下转型。例如下面的实例:

public class Test {
    public static void main(String[] args){
        Point point = new Point();
        //int -> Integer -> Object
        point.setX(116);
        point.setY(54);
        //向下转型
        int x = (Integer) point.getX();
        int y = (Integer) point.getY();
        System.out.println("Point :x="+x+" y="+y);
        //double -> Double -> Object
        point.setX(116.92);
        point.setY("纬度54.32");
        //向下转型
        Double x1 = (Double) point.getX();
        //会抛出ClassCastException异常
        Double y1 = (Double) point.getY();
        System.out.println("Point :x1="+x1+" y1="+y1);
    }
}
class Point{
    Object x = null;
    Object y = null;
    public Object getX() {
        return x;
    }
    public void setX(Object x) {
        this.x = x;
    }
    public Object getY() {
        return y;
    }
    public void setY(Object y) {
        this.y = y;
    }
}

那么Java中如何避免这样的情况发生呢?

Java中泛型出现就是解决出现这样的问题,所谓的“泛型”就是任意的数据类型。以下代码将利用泛型解决上面的问题。

public class Test {
    public static void main(String[] args){
        //实例化泛型
        Point<Integer,Integer> point = new Point<Integer,Integer>();
        point.setX(116);
        point.setY(54);
        int x = point.getX();
        int y =  point.getY();
        System.out.println("Point :x="+x+" y="+y);
        Point<Double,String> point1 = new Point<Double,String>();
        point1.setX(116.92);
        point1.setY("纬度54.32");
        Double x1 =  point1.getX();
        String y1 = point1.getY();
        System.out.println("Point :x1="+x1+" y1="+y1);
    }
}
//定义泛型类
class Point<T1,T2>{
    T1 x = null;
    T2 y = null;
    public T2 getY() {
        return y;
    }
    public void setY(T2 y) {
        this.y = y;
    }
    public T1 getX() {
        return x;
    }
    public void setX(T1 x) {
        this.x = x;
    }
}

实例中的T1和T2叫类型参数,类型参数是用来表示自定义标识符,用来传递数据的类型。Java中传值参数用小括号包围,泛型参数用尖括号包围,多个参数用逗号间隔,例如:

<T>或<T,E>

类型参数需要在类名后面给出。一旦给出了类型参数,就可以在类中使用了。类型参数必须是一个合法的标识符,习惯上使用单个大写字母,通常情况下,K 表示键,V 表示值,E 表示异常或错误,T 表示一般意义上的数据类型。

泛型类在实例化时必须指出具体的类型,也就是向类型参数传值,格式为:

className variable<dataType1, dataType2> = new className<dataType1, dataType2>();

也可以省略等号右边的数据类型,但是会产生警告,即:

className variable<dataType1, dataType2> = new className();

泛型的优点:使用泛型类时指明了数据类型,赋给其他类型的值会抛出异常,既不需要向下转型,也没有潜在的风险。

除了定义泛型类,还可以定义泛型接口和泛型方法,使用泛型方法时不必指明参数类型,编译器会根据传递的参数自动查找出具体的类型。

限制泛型的可用类型

通过 extends 关键字可以限制泛型的类型

public <T extends Number> T getMax(T array[]){
    T max = null;
    for(T element : array){
        max = element.doubleValue() > max.doubleValue() ? element : max;
    }
    return max;
}

<T extends Number> 表示 T 只接受 Number 及其子类,传入其他类型的数据会报错。这里的限定使用关键字 extends,后面可以是类也可以是接口。但这里的 extends 已经不是继承的含义了,应该理解为 T 是继承自 Number 类的类型。



Tags:Java泛型   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
从面向对象说起Java作为一门面相对象的语言,当然是支持面相对象的三大基本特性的,反手就蹦出三个词:封装、继承、多态。我们假设有三个类,动物、猫、狗。父类是动物Animal,有两...【详细内容】
2020-12-29  Tags: Java泛型  点击:(141)  评论:(0)  加入收藏
在学习泛型之前我们先回顾下Java的数据类型以及涉及到的一些概念。Java数据类型Java的两大数据类型分为基础类型和引用类型。基本类型的数值不是对象,不能调用对象的toString...【详细内容】
2020-08-20  Tags: Java泛型  点击:(58)  评论:(0)  加入收藏
引言 泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除。作...【详细内容】
2019-08-07  Tags: Java泛型  点击:(245)  评论:(0)  加入收藏
▌简易百科推荐
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(11)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(12)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(10)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(10)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(14)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(17)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(21)  评论:(0)  加入收藏
一、概述观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者发现,这么想来目标发生情况到观察...【详细内容】
2021-12-13  唯一浩哥    Tags:Java   点击:(16)  评论:(0)  加入收藏
相关文章
最新更新
栏目热门
栏目头条