java核心(九):泛型

一、泛型的目的

  • 泛型解决的是:向下转型时存在的安全隐患;
  • 泛型的核心是:在定义类或接口的时候,不需要显示地声明参数或属性的类型。

二、类中使用泛型

  • 注:在类、接口或方法中,泛型可以定义多个,泛型的名称自定义;
  • 注:使用泛型中,在显示指定具体类型时,只能是引用类型,不能是基本数据类型;
  • 注:使用泛型中,如果没有显示指定具体类型,则系统默认使用Object作为具体类型;
package com.study.Type;

/**
 * 在声明类的时候,定义了两个泛型:T、A
 * @param <T>
 * @param <A>
 */
class Fruit<T, A>{
    private T name;
    private A size;

    public Fruit(T name, A size) {
        this.name = name;
        this.size = size;
    }

    public void getInfo(){
        System.out.println("name: "+this.name+" , size: "+this.size);
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

    public A getSize() {
        return size;
    }

    public void setSize(A size) {
        this.size = size;
    }

}

public class Test {
    public static void main(String[] args) {
        Fruit<String,Integer> f1 = new Fruit<>("苹果",10);
        f1.getInfo();                   // name: 苹果 , size: 10
        String name2 = f1.getName();
        int size2 = f1.getSize();
        System.out.println(name2);      //  "苹果"
        System.out.println(size2);      //  10

        Fruit<String,String> f2 = new Fruit<>("苹果","直径10公分");
        f2.getInfo();                   // name: 苹果 , size: 直径10公分
    }
}

三、接口中使用泛型

package com.study.Type;

/**
 * 接口使用泛型:T
 */
interface IFruit<T>{
    public void print(T t);
}

/**
 * 实现类继续使用泛型:T
 */
class Apple<T> implements IFruit<T>{
    @Override
    public void print(T t) {
        System.out.println(t+" , "+t.getClass());
    }
}

/**
 * 实现类不使用泛型,指定接口的泛型参数类型
 */
class Orange implements IFruit<String>{
    @Override
    public void print(String s) {
        System.out.println(s+" , "+s.getClass());
    }
}

public class Test {
    public static void main(String[] args) {
        IFruit<String> a1 = new Apple<String>();
        a1.print("苹果");         //  苹果 , class java.lang.String

        IFruit<Integer> a2 = new Apple<Integer>();
        a2.print(100);           //  100 , class java.lang.Integer

        IFruit<String> orange = new Orange();
        orange.print("橘子");     //  橘子 , class java.lang.String
        //orange.print(100);     //语法错误:Error:(43, 22) java: 不兼容的类型: int无法转换为java.lang.String

    }
}

四、方法中使用泛型

class Test {
    public static void main(String[] args) {
        String str = print("苹果");
        System.out.println(str);    // 苹果

        int num = print(123);
        System.out.println(num);    //  123
    }

    /**
     *
     * @param t :   入参
     * @param <T> : 声明一个泛型
     * @return
     */
    public static  <T> T print(T t){
        return t;
    }
}

五、通配符"?"的使用

  • 注:使用通配符,只能取出数据,不能设置数据
package com.study.Type;

import java.util.Date;

    class Message<T> {
   private T msg;

    public Message(T msg) {
        this.msg = msg;
    }

    public T getMsg() {
        return msg;
    }
}

public class Test {
    public static void main(String[] args) {
        Message<String> f1 = new Message<>("苹果");
        print(f1);      //  苹果 , class java.lang.String

        Message<Integer> f2 = new Message<>(100);
        print(f2);      //  100 , class java.lang.Integer

        Message<Date> f3 = new Message<>(new Date());
        print(f3);      //  Fri Mar 08 15:26:25 CST 2019 , class java.util.Date
    }

    /**
     * 使用通配符"?",来接受泛型
     * @param message
     */
    public static void print(Message<?> message){
        System.out.println(message.getMsg()+"  ,  "+message.getMsg().getClass());
    }
}

六、通配符的引申用法

  1、"? extends 类" : 设置泛型上限。可以在声明上和方法参数上使用。

  • 如:"? extends Number":意味着只可以设置Number或Number的子类(如:Integer、Long、Double、......)

  2、"? super 类":设置泛型下限。可以在方法参数上使用。

  • 如:"? super Number":意味着只可以设置Number和Number的父类(Object)

七、分析:泛型

  1、Java泛型只存在于编辑期(.java文件中),在编译成字节码文件(.class文件)时,会把泛型擦除掉,替换为具体的类型

  在JAVA的虚拟机中并不存在泛型,泛型只是为了完善java体系,增加程序员编程的便捷性以及安全性而创建的一种机制,在JAVA虚拟机中对应泛型的都是确定的类型,在编写泛型代码后,java编译过程中会把这些泛型参数类型都擦除,用相应的确定类型来代替,代替的这一动作叫做类型擦除,而用于替代的类型称为原始类型,在类型擦除过程中,一般使用第一个限定的类型来替换,若无限定,则使用Object。

  2、泛型类的静态变量是共享的,于具体实例化的基本类型无关。

class GT<T>{
    /**
     * 泛型类的静态变量是共享的
     */
    public static int var = 0;
    public void nothing(T x){}
}

class StaticTest{
    public static void main(String[] args){
        GT<Integer> g1 = new GT<Integer>();
        g1.var = 1;
        System.out.println(g1.var);     // 1

        GT<String> g2 = new GT<String>();
        g2.var = 2;
        System.out.println(g1.var);     // 2
        System.out.println(g2.var);     // 2

        GT<Date> g3 = new GT<>();
        System.out.println(g1.var);     // 2
        System.out.println(g2.var);     // 2
        System.out.println(g3.var);     // 2
    }
}

原文地址:https://www.cnblogs.com/newbie27/p/10496213.html

时间: 2024-10-08 00:03:46

java核心(九):泛型的相关文章

Java Reflection(九):泛型

转载自并发编程网 – ifeve.com 内容索引运用泛型反射的经验法则泛型方法返回类型泛型方法参数类型泛型变量类型 我常常在一些文章以及论坛中读到说Java泛型信息在编译期被擦除(erased)所以你无法在运行期获得有关泛型的信息.其实这种说法并不完全正确的,在一些情况下是可以在运行期获取到泛型的信息.这些情况其实覆盖了一些我们需要泛型信息的需求.在本节中我们会演示一下这些情况. 运用泛型反射的经验法则 下面是两个典型的使用泛型的场景:1.声明一个需要被参数化(parameterizable)

Java核心 --- 泛型

CoreJava 泛型 java泛型的出现避免了强制类型转换,便于代码更好的被阅读 本文的写作参照了张孝祥的泛型介绍:http://www.itcast.cn/news/dbfd20f1/f4b1/412d/9b40/c1a81b8bf1da.shtml 更多疑问请参考:http://www.vaikan.com/java-generics-quick-tutorial/ 1.可以接收类型参数的类型在接受类型参数后变为泛型,但是,虽然是不同的泛型但是还是相同的类型 package com.yuk

Java核心 --- 枚举

Java核心 --- 枚举 枚举把显示的变量与逻辑的数字绑定在一起在编译的时候,就会发现数据不合法也起到了使程序更加易读,规范代码的作用 一.用普通类的方式实现枚举 新建一个终态类Season,把构造方法设为私有,因为枚举值不能随意增加因为不能new出这个类的对象,所以需要定义成员变量,把new写在类的内部这样,就可以在类的外部通过访问类的静态成员变量的方式访问到枚举值通过这样的方式,只能在类的外部使用在枚举类的内部定义的枚举值 类Season里面是可以有方法的,我们设置地球又公转了四分之一方法

Java核心编程快速学习

Java核心编程部分的基础学习内容就不一一介绍了,本文的重点是JAVA中相对复杂的一些概念,主体内容如下图所示. 反射reflect是理解Java语言工作原理的基础,Java编译器首先需要将我们编写的.java源文件编译为.class字节码,然后再JVM虚拟机上运行,接下来通过一个表格,来了解反射的基本操作. 功能 示例 泛化的Class引用 Class<?> intClass = int.class Class<? extends Number> bounded = int.cl

Java核心知识点学习----多线程 倒计时记数器CountDownLatch和数据交换的Exchanger

本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger. 一.CountDownLatch 1.什么是CountDownLatch? 倒计时计数器,调用CountDownLatch对象的CountDown()方法就将计数器减一,当计数到达0时,则所有等待者或者全部等待者开始执行. 2.如何用? new CountDownLatch(1); 直接new,其构造函数必须传一个int类型的参数,参数的意思是: c

Java基础学习笔记二十三 Java核心语法之反射

类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象. 链接指的是将Java类的二进制代码合并到JVM的运行状态之中的过程.在链接之前,这个类必须被成功加载.类的链接包括验证.准备和解析等几个步骤. 验证:是否有正确的内部结构,并和其他类协调一致. 准备:负责为类的静态成员分配内存,并设置默认初始化值 解析:

Java核心编程开发

Java核心编程开发,本部分内容侧重于java j2se核心部分,共50学时左右,主要内容包括:面向对象编程的六大基本原则及常见八种设计模式.Java核心类库的高级应用,如:文件输入输出流处理.反射.序列化.泛型.多线程.网络编程.DOM4J. 课程内容: 01.Java 中使用 IO 实现数据处理(共8讲) 02.Java 中使用XML实现数据处理(共6讲) 03.Java中的多线程编程(共5讲) 04.多线程高级应用(共5讲) 05.Java中的网络编程(共4讲) 06.网络编程高级应用(共

java5核心基础泛型(2):泛型在反射中的应用

如何通过反射获取指定参数类型的构造函数? 贴代码如下: package highBasic.generic; /** * 泛型入门 */ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; public class GenericTest { public static void main(St

Java面试题-泛型篇

139. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 好处: 1.类型安全,提供编译期间的类型检测 2.前后兼容 3.泛化代码,代码可以更多的重复利用 4.性能较高,用GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件. 140,Java的泛型是如何工作的 ? 什么是类型擦除 ?如何工作? 1.类型检查:在生成字节