我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java泛型的作用是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java泛型的作用是什么

这篇“Java泛型的作用是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java泛型的作用是什么”文章吧。

    简介

    泛型的作用就是把类型参数化,也就是我们常说的类型参数

    平时我们接触的普通方法的参数,比如public void fun(String s);参数的类型是String,是固定的

    现在泛型的作用就是再将String定义为可变的参数,即定义一个类型参数T,比如public static <T> void fun(T t);这时参数的类型就是T的类型,是不固定的

    从上面的String和T来看,泛型有着浓浓的多态的味道,但实际上泛型跟多态还是有区别的

    从本质上来讲,多态是Java中的一个特性,一个概念,泛型是真实存在的一种类型;

    正文中大部分示例都是以集合中的泛型为例来做介绍,因为用的比较多,大家都熟悉

    正文

    什么是类型参数

    类型参数就是参数的类型,它接受类作为实际的值

    白话一点来说,就是你可以把类型参数看作形参,把实际传入的类看作实参

    比如:ArrayList<E>中的类型参数E看做形参, ArrayList<String>中的类String看做实参

    如果你学过工厂设计模式,那么就可以把这里的ArrayList<E>看做一个工厂类,然后你需要什么类型的ArrayList,就传入对应的类型参数即可

    • 比如,传入Integer则为ArrayList<Integer>类

    • 比如,传入String则为ArrayList<String>类

    为啥要有泛型

    主要是为了提高代码可读性和安全性

    具体的要从泛型的演变史说起

    泛型的演变史

    从广义上来说,泛型很早就有了,只是隐式存在的;

    比如List list = new ArrayList(); //等价于List<Object> list = new ArrayList<>();

    但是这个时候的泛型是很脆弱的,可读性和安全性都很差(这个时期的集合相对于数组来说,优势还不是很大)

    首先,填充数据时,没有类型检查,那就有可能把Cat放到Dog集合中

    其次,取出时,需要类型转换,如果你很幸运的把对象放错了集合(有可能是故意的),那么运行时就会报错转换异常(但是编译却可以通过)

    不过到了JDK1.5,出现了真正意义上的泛型(类型参数,用尖括号<>表示);

    比如List<E>集合类,其中的E就是泛型的类型参数,因为集合中都是存的元素Element,所以用E字母替代(类似还有T,S,K-key,V-value);

    这个时候,程序的健壮性就提高了,可读性和安全性也都很高,看一眼就知道放进去的是个啥东西(这个时期的集合相对于数组来说,优势就很明显了

    现在拿List<Dog> list = new ArrayList<>();来举例说明

    首先,填充数据时,编译器自己会进行类型检查,防止将Cat放入Dog中

    其次,取出数据时,不需要我们手动进行类型转换,编译器自己会进行类型转换

    细心的你可能发现了,既然有了泛型,那我放进去的是Dog,取出的不应该也是Dog吗?为啥编译器还要类型转换呢?

    这里就引出类型擦除的概念

    类型擦除

    什么是类型擦除?

    类型擦除指的是,你在给类型参数<T>赋值时,编译器会将实参类型擦除为Object(这里假设没有限定符,限定符下面会讲到)

    所以这里我们要明白一个东西:虚拟机中没有泛型类型对象的概念,在它眼里所有对象都是普通对象

    比如下面的代码

    擦除前

    public class EraseDemo<T> {   private T t;   public static void main(String[] args) {         }   public T getT(){       return t;  }   public void setT(T t){       this.t = t;  }}

    擦除后

    public class EraseDemo {   private Object t;   public static void main(String[] args) {         }   public Object getT(){       return t;  }   public void setT(Object t){       this.t = t;  }}

    可以看到,T都变成了Object

    泛型类被擦除后的类型,我们一般叫它原始类型(raw type),比如EraseDemo<T>擦除后的原始类型就是EraseDemo

    相应的,如果你有两个数组列表,ArrayList<String>和ArrayList<Integer> ,编译器也会把两者都擦除为ArrayList

    你可以通过代码来测试一下

    ArrayList<String> list1 = new ArrayList<>();ArrayList<Integer> list2 = new ArrayList<>();System.out.println(list1.getClass() == list2.getClass());// 这里会打印true

    上面提到的限定符是干嘛的?

    限定符就是用来限定边界的,如果泛型有设置边界,比如<T extends Animal>,那么擦除时,会擦除到第一个边界Animal类,而不是Object类

    下面还是以上面的代码为例,展示下擦除前后的对比

    擦除前:

    public class EraseDemo<T extends Animal> {   private T t;   public static void main(String[] args) {         }   public T getT(){       return t;  }   public void setT(T t){       this.t = t;  }}

    擦除后:

    public class EraseDemo {   private Animal t;   public static void main(String[] args) {         }   public Animal getT(){       return t;  }   public void setT(Animal t){       this.t = t;  }}

    这里的extends符号是表示继承的意思吗?

    不是的,这里的extends只是表示前者是后者的一个子类,可以继承也可以实现

    之所以用extends只是因为这个关键词已经内置在Java中了,且比较符合情景

    如果自己再造一个关键词,比如sub,可能会使得某些旧代码产生问题(比如使用sub作为变量的代码)

    为什么要擦除呢?

    这其实不是想不想擦除的问题,而是不得不擦除的问题

    因为旧代码是没有泛型概念的,这里的擦除主要是为了兼容旧代码,使得旧代码和新代码可以互相调用

    泛型的应用场景

    • 从大的方向来说:

      • 用在类中:叫做泛型类,类名后面紧跟<类型参数>,比如ArrayList<E>

      • 用在方法中:叫做泛型方法,方法的返回值前面添加<类型参数>,比如:public <T> void  fun(T obj)

    是不是想到了抽象类和抽象方法?

    还是有区别的,抽象类和抽象方法是相互关联的,但是泛型类和泛型方法之间没有联系

    • 集中到类的方向来说:泛型多用在集合类中,比如ArrayList<E>

    如果是自定义泛型的话,推荐用泛型方法,原因有二:

    • 脱离泛型类单独使用,使代码更加清晰(不用为了某个小功能而泛化整个类)

    • 泛型类中,静态方法无法使用类型参数;但是静态的泛型方法可以

    通配符限定

    这里主要介绍<T>, <? extends T>, <? super T>的区别

    • <T>:这个是最常用的,就是普通的类型参数,在调用时传入实际的类来替换T即可,这个实际的类可以是T,也可以是T的子类

    比如List<String> list = new ArrayList<>();,这里的String就是实际传入的类,用来替换类型参数T

    • <? extends T>:这个属于通配符限定中的子类型限定,即传入实际的类必须是T或者T子类

    乍一看,这个有点像<T>类型参数,都是往里放T或者T的子类;

    但是区别还是挺多的,后面会列出

    • <? super T>:这个属于通配符限定中的超类型限定,即传入实际的类必须是T或者T的父类

    • <?>:这个属于无限定通配符,即它也不知道里面该放啥类型,所以干脆就不让你往里添加,只能获取(这一点类似<? extends T>)

    下面用表格列出<T>,<? extends T>, <? super T>的几个比较明细的区别

     <T><? extends T><? super T>
    类型擦除传入实参时,实参被擦为Object,但是在get时编译器会自动转为T擦到T擦到Object
    引用对象不能将引用指向子类型或者父类型的对象,比如:List<Animal> list = new ArrayList<Cat>();//报错能将引用指向子类型的对象,比如:List<? extends Animal> list = new ArrayList<Cat>();能将引用指向父类型的对象,比如:List<? super Cat> list = new ArrayList<Animal>();
    添加数据可以添加数据,T或者T的子类不能能,T或者T的子类

    下面我们用代码来演示下

    类型擦除:

    // <T>类型,传入实参时,擦除为Object,但是get时还是实参的类型List<Animal> list1 = new ArrayList<>();// 合法list1.add(new Dog());// 合法Animal animal = list1.get(0); // 这里不需要强转,虽然前面传入实参时被擦除为Object,但是get时编译器内部已经做了强制类型转换// <? extends T> 子类型的通配符限定,擦除到T(整个过程不再变)List<? extends Animal> list2 = list1;// 合法Animal animal2 = list2.get(0); // 这里不需要强转,因为只擦除到T(即Animal)// <? super T> 超类型的通配符限定,擦除到ObjectList<? super Animal> list3 = list1; // 合法Animal animal3 = (Animal)list3.get(0); // 需要手动强制,因为被擦除到Object

    将引用指向子类型或父类型的对象:

    // <T>类型,不能指向子类型或父类型List<Animal> list = new ArrayList<Dog>();// 报错:需要的是List<Animal>,提供的是ArrayList<Dog>// <? extends T> 子类型的通配符限定,指向子类型List<? extends Animal> list2 = new ArrayList<Dog>();// 合法// <? super T> 超类型的通配符限定,指向父类型List<? super Dog> list3 = new ArrayList<Animal>(); // 合法

    添加数据

    // <T>类型,可以添加T或者T的子类型List<Animal> list1 = new ArrayList<>();list.add(new Dog());// 合法// <? extends T> 子类型的通配符限定,不能添加元素List<? extends Animal> list2 = new ArrayList<Dog>();// 正确list2.add(new Dog()); // 报错:不能往里添加元素// <? super T> 超类型的通配符限定,可以添加T或者T的子类型List<? super Dog> list3 = new ArrayList<Animal>();list3.add(new Dog()); // 合法,可以添加T类型的元素list3.add(new Animal());//报错,不能添加父类型的元素

    下面针对上面的测试结果进行解惑

    先从<T>的报错开始吧

    为啥<T>类型的引用不能指向子类型,比如 List<Animal> list = new ArrayList<Dog>();

    首先说明一点,Animal和Dog虽然是父子关系(Dog继承Animal),但是List<Animal> 和 List<Dog>之间是没有任何关系的(有点像Java和Javascript)

    他们之间的关系如下图

    之所以这样设计,主要是为了类型安全的考虑

    下面用代码演示,假设可以将List<Animal>指向子类List<Dog>

    List<Animal> list = new ArrayList<Dog>();// 假设这里不报错list.add(new Cat()); //这里把猫放到狗里面了

    第二行可以看到,很明显,把猫放到狗里面是不对的,这就又回到了泛型真正出现之前的时期了(没有泛型,集合存取数据时不安全)

    那为啥<? extends T>就能指向子类型呢?比如List<? extends Animal> list = new ArrayList<Dog>();

    说的浅一点,原因是:这个通配符限定出现的目的就是为了解决上面的不能指向子类的问题

    当然,这个原因说了跟没说一样。下面开始正经点解释吧

    因为这个通配符限定不允许插入任何数据,所以当你指向子类型时,这个list就只能存放指向的那个集合里的数据了,而不能再往里添加;

    自然的也就类型安全了,只能访问,不能添加

    为什么<? extends T>不允许插入数据呢?

    其实这个的原因跟上面的修改引用对象是相辅相成的,合起来就是为了保证泛型的类型安全性

    考虑下面的代码

    List<Animal> list = new ArrayList<>();list.add(new Cat());list.add(new Dog());Dog d = (Dog) list.get(0); // 报错,转换异常

    可以看到,插入的子类很混乱,导致提取时转型容易出错(这是泛型<T>的一个弊端,当然我们写的时候多用点心可能就不会这个问题)

    但是有了<? extends T>之后,就不一样了

    首先你可以通过修改引用的对象来使得list指向不同的Animal子类

    其次你添加数据,不能直接添加,但是可以通过指向的Animal子类对象来添加

    这样就保证了类型的安全性

    代码如下:

    // 定义一个Dog集合List<Dog> listDog = new ArrayList<>();listDog.add(new Dog());// 让<? extends Animal>通配符限定的泛型 指向上面的Dog集合List<? extends Animal> list2 = listDog;// 这时如果想往里添加数据,只需要操作listDog即可,它可以保证类型安全listDog.add(new Dog());// 如果自己去添加,就会报错list2.add(new Dog());// 报错

    <? extends T>一般用在形参,这样我们需要哪个子类型,只需要传入对应子类的泛型对象就可以了,从而实现泛型中的多态

    <? super T>为啥可以插入呢?

    两个原因

    • 它只能插入T或者T的子类

    • 它的下限是T

    也就是说你随便插入,我已经限制了你插入的类型为T或者T的子类

    那么我在查询时,就可以放心的转为T或者T的父类

    代码如下:

    List<? super Dog> listDog = new ArrayList<>();listDog.add(new Dog());listDog.add(new Cat()); // 报错listDog.add(new Animal()); // 报错Dog dog = (Dog) listDog.get(0); // 内部被擦除为Object,所以要手动强转

    为啥<T>获取时,编译器会自动强转转换,到了这里<? super T>,就要手动转换了呢?

    这个可能是因为编译器也不确定你的要返回的T的父类是什么类型,所以干脆留给你自己来处理了

    但是如果你把这个listDog指向一个父类的泛型对象,然后又在父类的泛型对象中,插入其他类型,那可就乱了(又回到<T>的问题了,要自己多注意)

    比如:

    List<Animal> list = new ArrayList<>();list.add(new Cat()); // 加了Cat// 指向AnimalList<? super Dog> listDog = list;listDog.add(new Dog());list.add(new Cat()); // 报错list.add(new Animal()); // 报错Dog dog = (Dog) listDog.get(0); //报错:转换异常Cat-》Dog

    所以建议<? super T>在添加数据的时候,尽量集中在一个地方,不要多个地方添加,像上面的,要么都在<? super Dog>里添加数据,要么都在<Animal>中添加

    动态类型安全检查

    这个主要是为了跟旧代码兼容,对旧代码进行的一种类型安全检查,防止将Cat插入Dog集合中这种错误

    这种检查是发生在编译阶段,这样就可以提早发现问题

    对应的类为Collections工具类,方法如下图

    Java泛型的作用是什么

    代码如下

    // 动态类型安全检查,在与旧代码兼容时,防止将Dog放到Cat集合中类似的问题// === 检查之前 ===List list = new ArrayList<Integer>();// 添加不报错list.add("a");list.add(1);// 只有用的时候,才会报错Integer i = (Integer) list.get(0); // 这里运行时报错// === 检查之后 ===List list2 = Collections.checkedList(new ArrayList<>(), Integer.class);// 插入时就会报错list2.add("a"); // 这里编译时就报错,提前发现错误list2.add(1);

    以上就是关于“Java泛型的作用是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Java泛型的作用是什么

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Java泛型的作用是什么

    这篇“Java泛型的作用是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java泛型的作用是什么”文章吧。简介泛型的作用
    2023-06-29

    java中泛型Generic的作用是什么

    java中泛型Generic的作用是什么?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. 背景泛型技术诞生之前(JDK5以前),创建集合的类型都是Object 类型的元素
    2023-06-15

    Java中类型擦除式泛型的作用是什么

    本篇文章给大家分享的是有关Java中类型擦除式泛型的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java选择的泛型类型叫做类型擦除式泛型。什么是类型擦除式泛型呢?就
    2023-06-20

    java泛型指的是什么

    这篇文章主要讲解了“java泛型指的是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java泛型指的是什么”吧!概念1、泛型是指类型可以作为参数传递,本质上是类型参数。例如,当我们定义一
    2023-06-30

    java中什么是泛型

    本篇文章给大家分享的是有关java中什么是泛型,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程
    2023-06-14

    Java泛型的特性是什么

    本篇内容介绍了“Java泛型的特性是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!泛型概述泛型在java中有很重要的地位,在面向对象编程
    2023-06-02

    java使用泛型的优势是什么

    这篇文章主要介绍“java使用泛型的优势是什么”,在日常操作中,相信很多人在java使用泛型的优势是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java使用泛型的优势是什么”的疑惑有所帮助!接下来,请跟
    2023-06-20

    Java泛型擦除是什么

    这篇文章主要介绍了Java泛型擦除是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java泛型擦除是什么文章都会有所收获,下面我们一起来看看吧。泛型信息只存在于代码编译阶段,但是在java的运行期(已经生成
    2023-06-27

    java中的泛型指的是什么

    这篇文章主要讲解了“java中的泛型指的是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中的泛型指的是什么”吧!目录一、什么是泛型二、语法三、示例1、简单示例2、返回最大值-支持
    2023-06-20

    Java中的泛型是什么意思

    这篇文章主要介绍“Java中的泛型是什么意思”,在日常操作中,相信很多人在Java中的泛型是什么意思问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中的泛型是什么意思”的疑惑有所帮助!接下来,请跟着小编
    2023-06-03

    java泛型的局限是什么意思

    本篇内容主要讲解“java泛型的局限是什么意思”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java泛型的局限是什么意思”吧!1、泛型类的静态上下文中类型变量失效。 //静态域或者方法里不
    2023-06-20

    Java中泛型有什么用

    这篇文章主要介绍了Java中泛型有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。泛型1、简单泛型泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保
    2023-06-20

    Java泛型的设计方法是什么

    这篇文章主要讲解了“Java泛型的设计方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java泛型的设计方法是什么”吧!引言泛型是Java中一个非常重要的知识点,在Java集合类框架
    2023-06-17

    Java泛型的实现方式是什么

    本篇内容主要讲解“Java泛型的实现方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型的实现方式是什么”吧!Java 泛型实现方式Java 采用**类型擦除(Type eras
    2023-06-16

    C#中泛型的运作原理是什么

    这篇文章给大家介绍C#中泛型的运作原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一.泛型之前的故事#我们肯定会想到用object来作为类型参数,因为在C#中,所有类型都是基于Object类型的。因此Objec
    2023-06-07

    java泛型方法是什么意思

    这篇文章主要讲解了“java泛型方法是什么意思”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java泛型方法是什么意思”吧!说明1、泛型方法,是在调用方法的时候指明泛型的具体类型。2、泛型方
    2023-06-20

    Java泛型实现方式是什么

    这篇文章主要讲解了“Java泛型实现方式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java泛型实现方式是什么”吧!Java 泛型实现方式Java 采用**类型擦除(Type era
    2023-06-16

    Java中泛型擦除的原理是什么

    这篇文章将为大家详细讲解有关Java中泛型擦除的原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向对象
    2023-06-14

    java泛型的含义是什么及如何使用

    这篇“java泛型的含义是什么及如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“java泛型的含义是什么及如何使用”文
    2023-06-27

    java中使用泛型屏蔽类型的差异性是什么

    这篇文章主要为大家展示了“java中使用泛型屏蔽类型的差异性是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java中使用泛型屏蔽类型的差异性是什么”这篇文章吧。使用泛型屏蔽类型的差异性在C
    2023-06-02

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录