Java集合框架-------泛型

简介: Java集合框架-------泛型

JAVA自动装箱和自动拆箱:

装箱:将一个值封装称为一个对象的过程

举例:

Integer number=new Integer(100);

拆箱:从一个类型包装器中提取值的过程

举例:

int i=number.intValue();

装箱和拆箱是Java最初的版本中就存在的,他并不是Java1.5的新特性,自动拆装箱,当编译器编译时若发现是基本类型与包装类型之间相互赋值,将自动补充代码来完成转换工作,这个过程称为自动拆装箱。

自动拆箱和装箱:

自动装箱:当我们需要某个类型的对象时,该基本类型的数据类型自动被封装到与它相同类型的包装器中

举例:

Integer number=100;//直接将基本数据类型的值赋值给类包装器

自动拆箱与自动装箱相反,当我们需要一个值时,这个被装箱到对象中的值就会被自动的提取出来,不需要我们手动的去调用xxxvalue()方法。

举例:

int i=number;//直接将这个对象引用赋值给一个基本的变量即可

那么为什么要自动装箱和自动拆箱操作呢?


原因是可以大大简化基本类型变量和包装类对象之间的转换过程。


包装类:


通常情况下基本的数据类型,它只是一个类型而不是一个对象,JAVA是一个面向对象的编程语言,那么就需要将基本类型打包封装成对象,而将这些基本类型进行对象化的相关类就是包装类。


java定义了8个包装类,包括:Integer、Character、Byte、Short、Long、Float、Double、Boolean,其中Character和Boolean是直接继承自Object的,而其余6个包装类继承自java.lang.Number类。


即为了解决基本类型不能直接参与面向对象开发的问题,使得基本类型可以通过包装类的形式存在。## 泛型:

泛型是JDK5.0的新特征,泛型的本质是参数化类型,即程序中所操作的数据类型被指定为一个参数。


Java语言引入泛型的好处是安全简单,可以避免强制类型转换而产生的ClassCastException,在JDK5.0之前,在没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”。


泛型可以用在类,接口和方法的创建中,分别称为泛型类,泛型接口,泛型方法。


泛型头部定义格式如下:

[修饰符] class 类名<T>
[public] interface 接口名<T>
[public][static]<T> 返回值类型 方法名(T参数)

泛型类的定义和创建:

一般情况下,我们使用K,T,E,V等字母表示泛型类型参数,泛型类在命名上仍然要符合标识符的命名规则。

[public] class 泛型类名<形式类型参数1,形式类型参数1>
//形式类型参数列表用于指明当前泛型可接受的类型参数占位符的个数,参数是任意的,不同参数之间我们使用逗号隔开
{
类体
}

注:泛型的类型参数只能是引用数据类型,不能是基本数据类型


普通类在创建对象的过程中,都是直接进行创建的,但是泛型类在创建对象时,需要使用实际的参数类型去代替泛型类中的参数类型


举例:

person <String> name=new person<String>();//这里的String即为实际参数类型

泛型类的简单使用:

package generics;
public class generics<T> {
    private  T obj;
    public generics(T obj) {
        this.obj = obj;
    }
    public T getObj() {
        return obj;
    }
    public void setObj(T obj) {
        this.obj = obj;
    }
    public void showObj(){
        System.out.println("T的实际类型为:"+obj.getClass().getName());
    }
}
package generics;
public class generics1 {
    public static void main(String[]args){
    //定义泛型类generics的一个Integer类型
        generics<Integer> number=new generics<Integer>(67);
        number.showObj();
        int number1=number.getObj();
        System.out.println("数字为:"+number1);
        //定义泛型类generics的一个String类型
        generics<String> str=new generics<String>("hello,java");
        str.showObj();
        String str1=str.getObj();
        System.out.println("字符串为:"+str1);
    }
}

输出:

T的实际类型为:java.lang.Integer
数字为:67
T的实际类型为:java.lang.String
字符串为:hello,java

泛型接口:

定义如下:

[public] interface 接口名<T>
{
抽象方法
}

泛型接口的实现必须通过泛型类

泛型接口的简单使用:

package generics;
public class generics<T> implements text1<T>{//通过泛型类去实现泛型接口
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}
package generics;
public interface text1<T> {
    void show(T t);
}
package generics;
public class generics1 {
    public static void main(String[]args){
       generics<String> inter1=new generics<String>();//传递String类型
       inter1.show("我爱中国");
       generics<Double> inter2=new generics<Double>();//传递double类型
       inter2.show(99.0);
    }
}

输出:

我爱中国
99.0

泛型的优点:

泛型对程序带来的主要优点有两部分:

1:类型安全,泛型的主要目标是提高Java程序的类型安全。

2:消除强制转换类型,采用了泛型后,所有强制转换类型都是自动地和隐式的,这样就提高了代码的重用率。

package generics;
public class generics1 {
  private Object obj;
  public generics1(Object obj){
      this.obj=obj;
  }
  public Object getObj(){
      return obj;
  }
  public void showType(){
      System.out.println("实际类型是:"+obj.getClass().getName());
      //getClass()会获得对象执行时的Class实例,调用getName() 可以获取类的名称
  }
}

不强制转化:

generics1 grade=new generics1(90.3);
grade.showType();
double i=grade.getObj();
System.out.println("成绩="+i);

报错:

不使用泛型的情况下,必须进行强制类型转换!

package generics;
public class generics{
   public static void main(String[]args){
        generics1 grade=new generics1(90.3);
       grade.showType();
       double i=(double)grade.getObj();
       System.out.println("成绩="+i);
       generics1 name= new generics1("张三");
       name.showType();
       String name1=(String)name.getObj();
       System.out.println("名字是"+name1);
       generics1 number=new generics1(100);
       number.showType();
       int number1=(int)number.getObj();
       System.out.println("数字是"+number1);
       generics1 height=new generics1(180.2f);
       height.showType();
       Float weight1=(Float)height.getObj();
       System.out.println("身高是"+weight1);
   }
}

输出:

实际类型是:java.lang.Float
成绩=90.3
实际类型是:java.lang.String
名字是张三
实际类型是:java.lang.Integer
数字是100
实际类型是:java.lang.Float
身高是180.2

提醒:float的f是必须要加的,不加就编译出错!


float类型末尾加f(必须加) :


例如 float f = 90.3f

90.3是浮点数,默认是double类型,如果不加f去标记的话,那这个浮点数就是从double类型转换成了float类型,属于向下转型,必须得加小括号进行强制转换

通用符与受限的泛型类型:

泛型的类型通配符是"?“,使用”?"作为类型参数,代表任何可能的类型。

例如: Set<?>

它表示Set集合中可以存放任意一种类型的对象,泛型Set<?>是任何泛型Set的父类,Set<?>类型的变量在调用方法时是受到限制的;凡是必须知道具体类型参数的操作都不能执行。

package generics;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
public class generics{
   public static void main(String[]args){
       Set<String> set=new HashSet<String>();
       set.add("王俊凯");
       set.add("王源");
       set.add("易烊千玺");
   }
   public static void showELement(Set<?> v){
       v.add(new Date());//尝试创建具体参数类型!报错
       for(int i=0;i<v.size();i++){
           Object obj=v.elementAt(i);
           System.out.println(obj);
       }
       v.clear();
   }
}

报错:

原因为:形参v是通配符类型的Set对象,此处明确要添加的类型为Date,所以编译器阻止该操作,上文我们说到凡是必须知道具体类型参数的操作都不能执行。


在定义泛型类时,默认可以使用任何类型来实例化一个泛型类的对象,但也可以在用泛型类创建对象时对数据做出限制。

举例:

class ClassName<T extends anyClass>

其中anyClass是某个类或者接口,他表示泛型类型只能是anyClass的子类或者子接口,使用通配符"?"创建泛型类对象,通配符的主要作用是在创建一个泛型类对象时限制这个泛型类的类型是某个或者是继承该类的子类或者是实现某个接口的类.

举例:

ArrayList<? extends Number>

表示泛型类型只能是Number的子类。

受限泛型的简单使用:

package generics;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
public class generics<T extends Number>{//该泛型只能是Number的子类或者子接口
   private T obj;
   public generics(T obj){
       this.obj=obj;
   }
   public T getObj(){
       return obj;
   }
}
package generics;
public class generics1 {
public static void main(String[]args){
    generics<Integer> num1=new generics<Integer>(5);
    System.out.println("给出的参数是"+num1.getObj());
    generics<Double> num2=new generics<Double>(8.8);
    System.out.println("给出的参数是"+num2.getObj());
}
}

输出:

给出的参数是5
给出的参数是8.8

但如果参数传递的类型为如下所示的String类型,编译则不通过,原因为String并不是Number的子类。

generics<String> s=generics<String>("hello");

泛型的局限性:

1:泛型的参数不能被实例化
2:不能声明参数化类型的数组
3:不能用基本类型替换引用类型参数
4:不能定义带泛型的异常,不允许定义Throwable的泛型子类
5:不能在静态变量或者静态方法中引用类中声明的类型参数

Java泛型的主要作用是建立在具有类型安全的数据结构,它在集合框架中的应用非常广泛

相关文章
|
4天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
4天前
|
消息中间件 Java 数据库连接
Java 反射最全详解 ,框架设计必掌握!
本文详细解析Java反射机制,包括反射的概念、用途、实现原理及应用场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 反射最全详解 ,框架设计必掌握!
|
12天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
35 1
Spring 框架:Java 开发者的春天
|
10天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
6天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
8 1
|
12天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
12天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
40 5
|
10天前
|
Java API
[Java]泛型
本文详细介绍了Java泛型的相关概念和使用方法,包括类型判断、继承泛型类或实现泛型接口、泛型通配符、泛型方法、泛型上下边界、静态方法中使用泛型等内容。作者通过多个示例和测试代码,深入浅出地解释了泛型的原理和应用场景,帮助读者更好地理解和掌握Java泛型的使用技巧。文章还探讨了一些常见的疑惑和误区,如泛型擦除和基本数据类型数组的使用限制。最后,作者强调了泛型在实际开发中的重要性和应用价值。
12 0
[Java]泛型
|
4天前
|
Java API Apache
java集合的组内平均值怎么计算
通过本文的介绍,我们了解了在Java中计算集合的组内平均值的几种方法。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。无论是使用传统的循环方法,还是利用Java 8的Stream API,亦或是使用第三方库(如Apache Commons Collections和Guava),都可以有效地计算集合的组内平均值。希望本文对您理解和实现Java中的集合平均值计算有所帮助。
11 0
|
3月前
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。