java笔记(十三)

本文详细介绍了Java中的泛型,包括泛型的好处、类型擦除、泛型类、泛型方法、泛型接口、无界通配符、通配符的上限和下限限定,以及可变参数的使用。通过实例展示了泛型在类、方法和接口中的应用,强调了泛型在提高代码可读性和安全性方面的作用。此外,还讲解了StringBuilder类的基本使用,包括构造方法和添加、反转方法。

目录

泛型

泛型的好处

类型擦除

定义泛型

泛型类

泛型类语法结构

 泛型类使用的具体例子

泛型方法

泛型非静态方法

泛型静态方法

泛型方法使用的具体例子

泛型接口

泛型接口语法结构

 泛型接口使用的具体例子

 无界通配符

通配符的上限限定

 通配符的下限限定

可变参数

泛型方法与可变参数

StringBuilder概述

StringBuilder的构造方法

 StringBuilder的添加和反转方法


泛型

泛型的本质就是“数据类型的参数化”,处理的数据类型不是固定的,而是可以作为参数传入。我们可以把泛型理解为数据类型的一个占位符(类似:形式参数),即告诉编译器,在调用泛型时必须传入实际类型,这种参数类型可以在类,接口和方法中,分别被称为泛型类,泛型接口,泛型方法。

简单点说

  1. 把类型当作是参数一样传递
  2. <数据类型>只能是引用类型(类,接口,数组)

泛型的好处

在不使用泛型的情况下,我们可以使用Object类型来实现任意的参数类型,但是在使用时需要我们强制进行类型转换,这就要求程序员明确知道实际类型,不然可能引起类型转换错误;但是在编译期间我们无法识别这种错误,只能在运行期发现这种错误。使用泛型的好处就是可以在编译期间就识别出这种错误,有了更好的安全性;同时,所有类型转换由编译器完成,在程序员看来都是自动转换的,提高了代码的可读性。

总结一下,使用泛型主要有以下几个好处

  • 代码可读性更好【不用强制转换类型】
  • 程序更安全【只要编译时期没有警告,运行时期就不会出现ClassException异常】
  • 泛型主要是方便了程序员的代码编写,以及更好的安全检测。

类型擦除

编码时采用泛型写的类型参数,编译器会在编译时去掉,这称之为“类型擦除”。泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息,涉及类型转换任然是普通的强制类型转换。类型参数在编译后会被替代成Object,运行时虚拟机并不知道泛型。

所以如下几种情况是错误的

  • 基本类型不能用于泛型

Test<int> t;  这样的写法是错误的,我们可以使用对应的包装类;Test<Integer> t;

  • 不能通过类型参数创建对象

T elm=new T();运行时类型参数T会被替换成Object,无法创建T类型的对象,容易引起误解,所以在Java中不支持这种写法。

定义泛型

泛型字符可以是任何标识符,一般采用几个标记:E,T,K,V,N,?

泛型标记对应单词说明
EElement在容器中使用,表示容器中的元素
TType表示普通的Java类
KKey表示键,例如:Map中的键Key
VValue表示值
NNumber表示数值类型
?表示不确定的Java类型

泛型类

泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来。泛型类的具体使用方法是在类的名称后添加一个或多个类型参数声明,如<T><T,K,V>

泛型类语法结构

public class 类名<泛型表示符号>{

}

 泛型类使用的具体例子

用到了两个类 

 

 

 运行结果

泛型方法

泛型类中定义的泛型,在方法中也可以使用但是我们经常需要仅仅在某一个方法上使用泛型,这时候可以使用泛型方法。

泛型方法是指将方法的参数类型定义成泛型以便在调用时接受不同类型的参数。类型参数可以有多个,用逗号隔开,如<K,V>。定义时,类型参数一般放到返回值的前面。

调用泛型方法中,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推断出类型来。

泛型非静态方法

语法结构

public <泛型表示符号> void getName(泛型表示符号 name){

}

public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){

}

泛型静态方法

静态方法中使用泛型时有一种情况需要注意一下,那就是静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

语法结构

public static <泛型表示符号> void getName(泛型表示符号 name){

}

public static <泛型表示符号> 泛型表示符号 getName(泛型表示方法 name){

}

泛型方法使用的具体例子

下面这个方法使用了两个类

泛型接口

泛型接口和泛型类的声明方式一致,泛型接口的具体类型需要在实现类中进行声明

泛型接口语法结构

public interface 接口名<泛型表示符号>{

 泛型接口使用的具体例子

在接口中定义泛型,在接口实现类中需要传递具体的类型,然后重写方法

有一个接口,两个类

 

 

 运行结果如下

 无界通配符

“ ? ”表示类型通配符,用于替代具体的类型,它只能在“<>”中使用。可以解决当具体类型不确定的问题。

当一个类A使用了泛型,是一个泛型类。而另一个类B的方法要使用A类对象时,此时A类使用的泛型不能确定是什么类型,所以B类可以在方法中使用无界通配符。

具体实践例子如下(使用了三个类)


public class Generic<T>{
    private T flag;

    public void setFlag(T falg){
        this.flag=flag;
    }

    public T getFlag(){
    return this.flag;
    }
}
public class ShowMag{
    public void showFlag(Generic<?> generic){
        System.out.println(generic.getFlag());
    }
}
public class Tset{
    public static void main(String[] args){
        ShowMsg showMsg=new ShowMsg();
        Generic<Integer> generic =new Generic<>();
        generic.setFlag(20);
        showMsg.showFlag(generic);

        Generic<Number> generic1=new Generic<>();
        generic1.setFlag(50);
        showMsg.showFlag(generic1);

        Generic<String> generic2=new Generic<>();
        generic2.setFlag("oldWang");
        showMsg.showFlag(generic2);
    }
}

通配符的上限限定

上限限定表示通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口,该方法同样适用于泛型的上限限定

语法结构形如:public void method(Generic<? extends Number> generic){

}

 具体代码使用通配符上限限定的例子

下面的代码使用了三个类

public class Generic<T> {
   private T flag;
   public void setFalg(T flag){
       this.flag=flag;
   }
   public T getflag(){
       return this.flag;
   }
}
public class showMsg{
    public void ShowFlag(Generic<? extends Number> generic){
        System.out.println(generic.getFlag());
    }
}

Integer是Number的子类 

public class test02 {
    public static void main(String[] args) {
    showMsg show1=new showMsg();
    Generic<Integer> generic1=new Generic<>();
    generic1.setFalg(20);
    show1.ShowFlag(generic1);

    Generic<Number> generic2=new Generic<>();
    generic2.setFalg(50);
    show1.ShowFlag(generic2);
    }

}

 

 通配符的下限限定

下限限定表示通配符的类型是T类以及T类的父类或者T接口以及T接口的父接口

注意:该方法不适用泛型类

语法结构形如:public void showFlag(Generic<? super Integer> generic){

可变参数

 总结:

  1. 这里的变量其实是一个数组
  2. 如果一个方法有多个参数,包含可变参数,可变参数要放在后面

格式:修饰符 返回值类型 方法名(数据类型...变量名){}

例如:public static int sum(int...a){}  

由下面的代码可知,可变参数是以数组的形式存储的 ,可变形参的变量名就是数组名

 

由一下代码可知,形参是从左到右进行分配的 

 

泛型方法与可变参数

在泛型方法中,泛型也可以定义可变参数类型

语法结构:   修饰符 <泛型表示符号> 返回值类型 方法名(泛型表示符号...args){}

例如:             public <T>void method(T...args){}

具体实践例子

1.在MethodGeneric类中创建一个方法

 2.在Test5类中对MethodGeneric类的method方法进行调用,运行结果如下

StringBuilder概述

StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是StringBuilder对象中的内容是可变的

String和StringBuilder的区别

  • String:内容是不可变的
  • StringBuilder:内容是可变的

StringBuilder的构造方法

  • public StringBuilder()                       创建一个空白可变字符串对象,不含有任何内容
  • public StringBuilder(String str)          根据字符串的内容,来创建可变字符串对象 

 StringBuilder的添加和反转方法

  • public StringBuilder append(任意类型)   : 添加数据,并返回对象本身
  • public StringBuilder reverse()                  :返回相反的字符序列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笃岩_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值