商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > java要有java的范儿

java要有java的范儿

  发布于2026-07-19 阅读(0)

扫一扫,手机访问

Ja va 泛型

泛型是 Ja va 语言中一个非常实用的特性,它允许你写代码的时候先不把类型定死,等到真正用的时候再指定。打个比方,就像设计一个“盒子”,你只告诉别人“这个盒子能装东西”,但具体装什么——是苹果还是书本——由使用者决定。这类设计在集合框架里用得最多,因为集合在声明阶段根本不知道你会往里塞什么类型的对象。

一、泛型的概念

用专业点的话说,泛型就是在定义类、接口或方法时,用一个标识符(比如 TE)来表示某个属性的类型,或者方法的返回值类型、参数类型。这个类型参数会在你实际使用的时候确定下来——比如继承、实现接口、声明变量、创建对象时传入具体的类型实参。

二、泛型的引入背景

Ja va 集合框架在 JDK 1.5 之前,容器里能装什么类型是不确定的,所以设计者把元素类型统一设成了 Object。这样一来,你从集合里取出来的东西都得强转,而且直到运行时才能发现类型不对。JDK 1.5 引入泛型之后,情况就完全不同了——除了元素的类型不确定,其他部分(比如元素怎么存、怎么管理)都是确定的,所以干脆把元素类型设计成一个参数,也就是泛型。像 CollectionListArrayList 里的 E,就是那个类型参数。

一个简单的例子

先看一段没有泛型时的代码:

import ja va.util.ArrayList;
import ja va.util.List;

public class test {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("string");
        list.add(100);
        for (int i = 0; i < list.size(); i++) {
            String name = (String) list.get(i); // 1
            System.out.println("name:" + name);
        }
    }
}

运行这段代码会抛出 ClassCastException,因为 ArrayList 里同时塞了 StringInteger,而循环里却把它们都当成 String 强转,自然就出错了。

引入泛型之后,问题迎刃而解:

import ja va.util.ArrayList;
import ja va.util.List;

public class test {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("string");
        // list.add(100); // 编译错误
        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i); // 2
            System.out.println("name:" + name);
        }
    }
}

如果你试着加一个 100,编译器会直接报错:add(int) 找不到合适的方法 —— 参数不匹配,int 无法转换为 String。这就是泛型带来的编译期类型检查,把运行时错误提前挡在了门外。

泛型的好处总结一下:

  • 集合接口和集合类在 JDK 5.0 之后都改成了带泛型的结构。
  • 实例化集合时可以指明具体的泛型类型,之后内部所有用到泛型的地方(方法、构造器、属性等)都会被替换成你指定的类型,比如 add(E e) 变成 add(Integer e)
  • 注意:泛型的类型必须是引用类型,不能用基本数据类型。需要基本类型时用对应的包装类,比如 Integer 代替 int
  • 如果实例化时没指明泛型类型,默认就是 Object

三、泛型类

一个泛型类就是拥有一个或多个类型变量的类。看个简单的例子:

public class test {
    public static class Point {
        private T var;
        public void setVar(T x) {
            this.var = x;
        }
        public T getVar() {
            return this.var;
        }
    }
    public static void main(String[] args){
        Point p = new Point();
        p.setVar(new Float(100.12f));
        System.out.println(p.getVar());
    }
}

尖括号里的 T 是形式类型参数,你可以随便起名字(比如 EKV)。当类被使用的时候,就会传入实际类型参数,比如这里的 Float。需要说明的是,泛型类只能用在成员变量上,而且只能使用引用类型。

四、泛型方法

泛型方法有自己的规则:类型参数声明部分(用尖括号括起来)必须放在方法返回类型之前。可以声明一个或多个类型参数,用逗号隔开。类型参数可以用来声明返回值类型,也可以作为方法参数类型的占位符。方法体和其他方法一样,但注意类型参数只能代表引用类型,不能是原始类型(intdoublechar 等)。

public class MethodTest {
    int var = 100;
    String varStr = "Hello Datawhale";
    public  T Method(T a) {
        return a;
    }
    public static void main(String[] args) {
        MethodTest t = new MethodTest();
        System.out.println(t.Method(t.var));
        System.out.println(t.Method(t.varStr));
    }
}

五、泛型接口

实现泛型接口时,可以在子类中指定具体的类型参数。比如下面这个例子:

class InfoImpl implements Info{ // 定义泛型接口的子类
    private String var ; // 定义属性
    public InfoImpl(String var){ // 通过构造方法设置属性内容
        this.setVar(var) ;
    }
    @Override
    public void setVar(String var){
        this.var = var ;
    }
    @Override
    public String getVar(){
        return this.var ;
    }
}
public class GenericsDemo24{
    public void main(String arsg[]){
        InfoImpl i = new InfoImpl("harvic");
        System.out.println(i.getVar()) ;
    }
};

六、类型通配符

当你不确定具体类型参数时,可以用 ? 代替,它表示未知类型。类型通配符只能用在声明类型、方法参数上,不能用在定义泛型类上。看个例子:

public class match {
    public static void test(List list) {
        List list2;
        list2 = new ArrayList();
        list2 = new ArrayList();
        list2 = new ArrayList();
    }
    public static void main(String[] args) {
        test(new ArrayList());
        test(new ArrayList());
    }
}

这段代码里,List 可以接受任何类型的 ArrayList,但你不能往里面写数据(除了 null),因为类型不确定,编译器不让你做任何可能破坏类型安全的操作。

本文转载于:https://blog.csdn.net/weixin_45014634/article/details/119150753 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。
  • using namespace 使用中遇到的问题怎么解决 正版软件
    using namespace 使用中遇到的问题怎么解决
    命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,
    10天前 0
  • c语言函数递归 实操经验总结:这些技巧很实用 正版软件
    c语言函数递归 实操经验总结:这些技巧很实用
    理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接
    10天前 0
  • c语言函数递归 怎么选?常见方案对比分析 正版软件
    c语言函数递归 怎么选?常见方案对比分析
    递归函数的基本概念与适用场景在C语言编程中,递归是一种函数调用自身的编程技巧。它并非适用于所有问题,但在处理某些具有自相似结构的问题时,能提供极其清晰和优雅的解决方案。递归的核心思想是将一个大规模问题分解为一个或多个同类型但规模更小的子问题,直到子问题简单到可以直接求解。典型的适用场景包括树形结构的
    10天前 0
  • Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解 正版软件
    Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解
    理解内存管理的基石在Objective-C的编程世界中,内存管理是开发者必须掌握的核心技能之一。它直接关系到应用的性能、稳定性与资源利用效率。与一些采用自动垃圾回收机制的语言不同,Objective-C在很长一段时间里,依赖一套基于引用计数的、需要开发者部分介入的管理规则。这套规则的核心思想是明确的
    10天前 0
  • 如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏 正版软件
    如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏
    理解 dealloc 的角色与时机在 iOS 应用开发中,内存管理是保障应用性能与稳定性的基石。dealloc 方法是 Objective-C 中对象生命周期结束时的关键回调,它标志着对象即将被系统回收内存。正确理解其触发时机至关重要:当一个对象的引用计数降为零时,运行时系统会自动调用该对象的 de
    10天前 0