文档章节

java泛型详解

一贱书生
 一贱书生
发布于 2017/04/11 14:04
字数 3764
阅读 11
收藏 0

       在日常的开发中,我们会看到别人的框架很多地方会使用到泛型,泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。本篇博客我们就来详细解析一下泛型的知识。

泛型类定义及使用

使用泛型有什么好处呢?首先我们先看一个例子,假设我们有两个类,代码如下:

#StringClass 
public class StringClass {
    private String x ;
    private String y ;

    public String getY() {
        return y;
    }

    public void setY(String y) {
        this.y = y;
    }

    public String getX() {
        return x;
    }

    public void setX(String x) {
        this.x = x;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
#IntClass 
public class IntClass {
    private int x ;
    private int y ;

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

观察上面两个类StringClass 和IntClass,他们除了变量类型不一样,一个是String一个是int以外,其它并没有什么区别!那我们能不能合并成一个呢?通过泛型就可以解决,首先看一下泛型的类是怎么定义的:

public class ObjClass<T> {

    private T x ;
    private T y ;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

那么这时候上面的两个类就可以通过泛型的设置,相应生成

 ObjClass<String> stringClass = new ObjClass<String>();
        stringClass.setX("haha");

        ObjClass<Integer> intClass = new ObjClass<Integer>();
        intClass.setX(100);

        Log.d("yyy", "stringClass:" + stringClass.getX() + ",intClass:" + intClass.getX());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里写图片描述
从结果中可以看到,我们通过泛型实现了开篇中StringClass类和IntClass类的效果。

接下来介绍泛型如何定义及使用:
1.首先需要定义泛型:ObjClass
ObjClass ,即在类名后面加一个尖括号,括号里是一个大写字母。这里写的是T,其实这个字母可以是任何大写字母,无论使用哪个字母,意义都是相同的。

2.在类中使用泛型
这个T表示派生自Object类的任何类,比如String,Integer,Double等等。这里要注意的是,T一定是派生于Object类的。

private T x ;
    private T y ;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.使用泛型类
泛型类的使用代码如下:

  ObjClass<String> stringClass = new ObjClass<String>();
        stringClass.setX("haha");

        ObjClass<Integer> intClass = new ObjClass<Integer>();
        intClass.setX(100);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

首先,需要构造一个实例:

 ObjClass<String> stringClass = new ObjClass<String>();
  • 1
  • 1

泛型类的构造则需要在类名后添加上,即一对尖括号,中间写上要传入的类型。
因为我们构造时,是这样的:ObjClass,所以在使用的时候也要在ObjClass后加上类型来定义T代表的意义。

尖括号中,你传进去的是什么,T就代表什么类型。这就是泛型的最大作用,我们只需要考虑逻辑实现,就能拿给各种类来用。

多泛型变量定义

1.多泛型变量定义
我们不止可以在类中设置一个泛型变量T,还可以声明多个泛型变量,写法如下:

public class ObjClass<T,U> 
  • 1
  • 1

也就是在原来的T后面用逗号隔开,写上其它的任意大写字母即可,如果还有多个,依然使用逗号分隔开即可,则我们前面定义的泛型类就会变成下面这样:

public class ObjClass<T,U> {

    private T x ;
    private U y ;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public U getY() {
        return y;
    }

    public void setY(U y) {
        this.y = y;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  ObjClass<String,Integer> stringClass = new ObjClass<String,Integer>();
        stringClass.setX("haha");
        stringClass.setY(100);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

从上面的代码中,可以明显看出,就是在新添加的泛型变量U用法与T是一样的。

2.泛型的字母规范
虽然在类中声明泛型任意字母都可以,但为了可读性,最好遵循以下的规范:

 E — Element,常用在java Collection里,如:  List<E>,Iterator<E>,Set<E>
 K,V — Key,Value,代表Map的键值对
 N — Number,数字
 T — Type,类型,如String,Integer等等
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

泛型接口定义及使用

在接口上定义泛型与在类中定义泛型是一样的,代码如下:

interface MsgClass<T> {
    public T getMsg() ;
    public void setMsg(T x);
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

我们可以利用泛型类来构造填充泛型接口

public class Message<T,U> implements MsgClass<T>{

    private T msg;
    @Override
    public T getMsg() {
        return msg;
    }

    @Override
    public void setMsg(T msg) {
        this.msg = msg;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这个类中,我们构造了一个泛型类Message,然后把泛型变量T传给了MsgClass,这说明接口和泛型类使用的都是同一个泛型变量。

我们还可以构造一个多个泛型变量的类,并继承自MsgClass接口:

public class Message<T,U> implements MsgClass<T>{
    private U name;
    private T msg;
    @Override
    public T getMsg() {
        return msg;
    }

    @Override
    public void setMsg(T msg) {
        this.msg = msg;
    }

    public U getName() {
        return name;
    }

    public void setName(U name) {
        this.name = name;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

泛型函数定义及使用

我们不但可以在类声明中使用泛型,还可以在函数声明中也使用泛型,使用如下:

public class ObjClass {
    //静态函数
    public static <T> void StaticMethod(T a) {

    }

    //普通函数
    public <T> void OrgnicMethod(T a) {

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上面分别是静态泛型函数和常规泛型函数的定义方法,与以往方法的唯一不同点就是在返回值前加上来表示泛型变量。

无论哪种泛型方法都有两种使用方法:


//静态方法
ObjClass.StaticMethod("adfdsa");//使用方法一
ObjClass.<String>StaticMethod("adfdsa");//使用方法二
//常规方法
ObjClass objClass = new ObjClass();
objClass.OrgnicMethod(new Integer(111));//使用方法一
objClass.<Integer>OrgnicMethod(new Integer(111));//使用方法二
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

方法一,隐式传递了T的类型,这种隐式的传递方式,代码不利于阅读和维护。因为从外观根本看不出来你调用的是一个泛型函数。
方法二,例如上面例子中,将T赋值为Integer类型,这样OrgnicMethod(T a)传递过来的参数如果不是Integer那么编译器就会报错。

当然泛型函数的返回值也可以使用泛型表示:

public static <T> List<T> parseArray(String response,Class<T> object){  
    List<T> modelList = JSON.parseArray(response, object);  
    return modelList;  
}  
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

函数返回值是List类型。和void的泛型函数不同,有返回值的泛型函数要在函数定义的中在返回值前加上标识泛型;还要说明的是,上面中,使用Class传递泛型类Class对象

泛型数组

泛型同样可以用来定义在数组上

         //定义  
        public static <T> T[] fun1(T...msg){  // 接收可变参数    
            return msg ;            // 返回泛型数组    
        }
        //使用  
        public static void main(String args[]){
            Integer i[] = fun1(8,9,8,44) ;
            Integer[] result = fun1(i) ;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

定义了一个静态函数,然后定义返回值为T[],参数为接收的T类型的可变长参数。

泛型的通配符

在开发中对象的引用传递(向上向下传递)是最常见的,但是,在泛型的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则不能传递。

例如,如下没有进行泛型类型匹配,一个是String,一个是Object类型。

class Info<T>{
    private T var ;        // 定义泛型变量
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){   
        return this.var.toString() ;
    }
};

public class demo1 {
        public static void main(String args[]) {
            // 使用String为泛型类型
            Info<String> i = new Info<String>();        
            i.setVar("ABCD");
            //把String泛型类型的i对象传递给Object泛型类型的temp。
            fun(i);                   
        }

        // 接收Object泛型类型的Info对象
        public static void fun(Info<Object> temp) {        
            System.out.println("内容:" + temp);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

编译发生错误。

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The method fun(Info<Object>) in the type demo1 is not applicable for the arguments (Info<String>)

    at Thread1.demo1.main(demo1.java:18)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

泛型对象进行引用传递的时候,类型必须一致,如果非要传递,则可以将fun方法中Info参数的泛型取消掉(变成 void fun(Info temp))。、

以上确实改进了功能,但是似乎不是很妥当,毕竟之前指定过泛型。

以上程序在fun()方法中使用"Info<?>"的代码形式,表示可以使用任意的泛型类型对象,这样的话fun()方法定义就合理了,但是使用以上方法也有需要注意的地方,

即:如果使用“?“接收泛型对象的时候,则不能设置被泛型指定的内容。

class Info<T>{
    private T var ;        
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    
        return this.var.toString() ;
    }
};
public class GenericsDemo{
    public static void main(String args[]){
        Info<String> i = new Info<String>() ;       
        i.setVar("ABCD") ;                            
        fun(i) ;
    }
    public static void fun(Info<?> temp){        
        System.out.println("内容:" + temp) ;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

如果使用”?“意味着可以接收任意的内容,但是此内容无法直接使得用”?“修饰的泛型的对象进行修改。如下就会出问题:

class Info<T>{
    private T var ;        
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){   
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<?> i = new Info<String>() ;       
        i.setVar("ABCD") ;                            
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

运行结果:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The method setVar(capture#1-of ?) in the type Info<capture#1-of ?> is not applicable for the arguments (String)

    at Thread1.demo1.main(demo1.java:17)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在使用”?“只能接收,不能修改。

泛型的上限

class Info<T>{
    private T var ;        
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    
        return this.var.toString() ;
    }
};
public class GenericsDemo{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        
        Info<Float> i2 = new Info<Float>() ;            
        i1.setVar(30) ;                                    
        i2.setVar(30.1f) ;                                
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? extends Number> temp){    // 只能接收Number及其Number的子类
        System.out.print(temp + "、") ;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

运行成功。但是,如果传入的泛型类型为String的话就不行,因为String不是Number子类。
在类中使用泛型上限。

class Info<T extends Number>{    // 此处泛型只能是数字类型
    private T var ;        
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){   
        return this.var.toString() ;
    }
};
public class demo1{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如果在使用Info的时候设置成String类型,则编译的时候将会出现错误(String不是Number子类)
注意:利用<? extends Number>定义的变量,只可取其中的值,不可修改

原因如下:
因为Info的类型为 Info

泛型的下限

<? super XXX>表示填充为任意XXX的父类

class Info<T>{
    private T var ;        
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){    
        return this.var.toString() ;
    }
};
public class GenericsDemo21{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 
        Info<Object> i2 = new Info<Object>() ;        // 
        i1.setVar("hello") ;
        i2.setVar(new Object()) ;
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? super String> temp){    // 只能接收String或Object类型的泛型,String类的父类只有Object类
        System.out.print(temp + "、") ;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Object类和String类都是String的父类,所有运行成功,但是如果此时用Integer则会出错,因为integer并不是String父类。

注意:使用super通配符:能存不能取
如何理解呢?假设有3个类,继承关系如下:

class CEO extends Manager {  
}  

class Manager extends Employee {  
}  

class Employee {  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

然后书写如下代码:

List<? super Manager> list;  
list = new ArrayList<Employee>();  
//存  
list.add(new Employee()); //编译错误  
list.add(new Manager());  
list.add(new CEO());  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

为什么而list.add(new Employee());是错误的?
因为list里item的类型是

List<Employee> list = new ArrayList<Employee>();  
list.add(new Manager());  
list.add(new CEO()); 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在这里,正因为Manager和CEO都是Employee的子类,在传进去list.add()后,会被强制转换为Employee!
现在回过头来看这个:

List<? super Manager> list;  
list = new ArrayList<Employee>();  
//存  
list.add(new Employee()); //编译错误  
list.add(new Manager());  
list.add(new CEO());  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

编译器无法确定<? super Manager>的具体类型,但唯一可以确定的是Manager()、CEO()肯定是<? super Manager>的子类,所以肯定是可以add进去的。但Employee不一定是<? super Manager>的子类,所以不能确定,不能确定的,肯定是不允许的,所以会报编译错误。

最后强调一下,List<? super Manager> list取出的只能是Object 类型,这里虽然看起来是能取的,但取出来一个Object类型,是毫无意义的。所以才有了“super通配符:能存不能取”的结论。

总结
1)使用?可以接收任意泛型对象。

2)泛型的上限:?extends 类型(能取不能存)。

3)泛型的下限:?super 类型? super 通配符(能存不能取)。

本文转载自:http://blog.csdn.net/u012124438/article/details/69487962

一贱书生
粉丝 19
博文 724
码字总数 600123
作品 0
私信 提问
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
2018/06/21
0
0
Java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一

对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下。 本文参考java 泛型详解、Java中的泛型方法、 java泛型详解 1 概述 泛型在j...

hensemlee
2018/09/23
0
0
一份关于 Java、Kotlin 与 Android 的学习笔记

JavaKotlinAndroidLearn 这是一份关于 Java 、Kotlin 、Android 的学习笔记,既包含对基础知识点的介绍,也包含对一些重要知识点的源码解析,笔记的大纲如下所示: Java 重拾Java(0)-基础知...

叶应是叶
2018/08/08
0
0
大数据开发培训:0基础学习Java编程语言有哪些知识点?

Java 技术通用、高效、具有平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网等,学习Java首先要知道学习知识点有哪些。在这就用加米谷大数据培训...

加米谷大数据
2018/07/25
0
0
Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh
2018/06/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

设计模式-简介

设计模式简介 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案...

HOT_POT
21分钟前
2
0
SpringBoot版

使用外部Tomcat来启动程序,而不是用默认的Application的main()来启动。 因为,使用Application的main()来启动,修改页面的时候,刷新不会立即有反应。而是要make一下(Ctrl+F5) 而且还要加入...

流小文
25分钟前
1
0
Disable Autostart of MySQL Server on Ubuntu

OSC Markdown Editer 真香,笔记一篇,懒得转中文,如有表述问题,请不吝指出,先谢为敬! OS: Ubuntu 19.04 When the MySQL server is installed, it automatically started with the OS. I...

Iridium
47分钟前
2
1
OpenStack RDO + S3

Packstack(RDO) installation "sync db timeout" issue version: openstack-packstack-13.0.0-0.1.0rc1.el7.noarchopenstack-packstack-puppet-13.0.0-0.1.0rc1.el7.noarch add timeout =>......

Firxiao
49分钟前
2
0
java运算符的优先级

https://www.cnblogs.com/zjfjava/p/5996666.html

南桥北木
55分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部