[JavaSE]泛型

目录

预备知识:

jdk1.5新特性:泛型 枚举 注解可变参数foreach循环静态导入向上转型(90%):父类 父类引用=子类实例   //以物换物向下转型(1%):子类 子类引用=(子类)父类实例

泛型类:TKV

泛型方法泛型类与泛型方法共存时规范

通配符

?extends类:T extends 类:? extends 类:? super 类:

泛型接口

类型擦除

java语法糖


回顾C语言,普通指针提供两方面的信息,1地址2内存大小

void*只有地址信息.没有内存大小信息

一个函数需要支持多种不同类型的参数就可以使用void*

起到的效果:让一个类或者方法可以使用不同类型的参数--引入泛型

jdk1.5新特性:泛型 枚举 注解

可变参数

要求方法可以接收任意个整数并且返回他们相加的结果

类型 参数名称

  • 一个方法有且只有一个可变参数,放在方法的最后一个参数
  • 可变参数的本质----还是数组

foreach循环

foreach语法可以和很多类搭配,只要这个类实现了iterable接口,就可以使用

---用于数组与类集的简单输出(修改的话还是用for循环)

for(数据类型 临时变量 : 数组(集合)) { // 循环次数为数组长度,而每一次循环都会顺序取出数组中的一个元素赋值给临时变量 }

举例:

public class TestDemo { 
public static void main(String[] args) { 
int[] data = new int[] { 1, 2, 3, 4, 5 }; // 原始数组
 for (int i : data) { // 将数组中每个元素赋值给i 
 System.out.println(i); // 这种循环避免了角标的问题 
        } 
    } 
}

静态导入

package www.se.SE.util;
public class MyMath{
public static int add(int x,int y){
return x+y;
}
public static int mul(int x,int y){
return x*y;
}
}
package www.se.SE.util;
import static www.se.SE.util.MyMath.*;//静态导入
public class Test1{
public static void main(String[] args){
 System.out.println(add(10,20));
 System.out.println(mul(30,10));
 }
}

描述坐标的属性类:

1 私有Object类属性x      私有Object类属性y

2设置x y的值

3自动拆箱 把Object类的值强行转换为Integer类型(double /string)

package se.SE.practice;
class point{
    private Object x;
    private Object y;

    public Object getX() {
        return x;
    }

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

    public Object getY() {
        return y;
    }

    public void setY(Object y) {
        this.y = y;
    }
}
public class Thread1 {
    public static void main(String[] args) {
        point point1 = new point();
        point1.setX(10);
        point1.setY(20);
        int x = (Integer) point1.getX();//把Object类型的变量强行转为Integer类型
        int y = (Integer) point1.getY();//自动拆箱,类型之间的转换只能在引用类型中转换
        System.out.println(x + " " + y);
    }
}

注意:由于设置方的错误,将坐标内容设置成了double类型(eg.20.9)String类型(eg.北纬89°),但是接收方不知道

不可以将String类型强制转换为int 类型,否则系统会报出:ClassCastException异常,

总结:向下转型存在安全隐患

向上转型(90%):父类 父类引用=子类实例   //以物换物

天然发生(认爹)
应用场景:参数统一化

test(new Person());
//per=new Studnet();//子类指向父类
test(new Student());
Person per=new Student();//子类一定可以变成父类 向上转型
per.fun();

向下转型(1%):子类 子类引用=(子类)父类实例

//剩下1%不转(认儿)

Student stu=(Student)per;//向下转型

需要强转,发生向下转型之前,一定首先发生向上转型

否则会抛出一个ClassCastException(运行时异常,类型转换异常,发生在两个毫无关系的类之间强转时)

泛型类:

所谓的泛型,就是类定义的时候,并不会设置类的属性和方法参数的任何类型

在使用的时候再定义

格式:

class MyClass<T>{
    private T value1;
    public T getValue1() {
        return value1;
    }
    public void setValue1(T value1) {
        this.value1 = value1;
    }
}

语法:

T:

被称为类型参数,用于指代任意类型

 代表一般的类

E:

泛型类中的属性

K V :

见于map集合hsjb

package se.SE.practice;
class MyClass<T>{
    private T value1;
    public T getValue1() {
        return value1;
    }
    public void setValue1(T value1) {
        this.value1 = value1;
    }
}
public class Test{
    public static void main(String[] args) {
        MyClass<String> myClass=new MyClass<String>( );//使用的时候定义类型
        myClass.setValue1("2019a");
        System.out.println(myClass.getValue1());
        MyClass<Integer> myClass2=new MyClass<Integer>();
        myClass2.setValue1(10);
        System.out.println(myClass2.getValue1());
    }
}

泛型只允许接收类,所有基本类型必须使用包装类 

泛型方法

格式:

<T>:表示此方法是泛型方法

T:参数t的返回值类型

 public <T> void  MyMethod(T t){
        System.out.println(t);
    }
package se.SE.practice;
class MyClass{
 public <T> void MyMethod(T t){
        System.out.println(t);
    }
}
public class Test{
    public static void main(String[] args) {
    MyClass myClass=new MyClass();
    myClass.MyMethod(10);
    myClass.MyMethod("78A");
    myClass.MyMethod(10.667);
    }
}

泛型类与泛型方法共存时:

泛型类中的类型参数与泛型方法类型参数没有关系,泛型方法中的类型参数始终以自己定义的类型参数为准

规范:

泛型方法类型参数与泛型类的类型参数不要同名

 

引入通配符:

引入泛型后,在方法的参数上,参数的类型较多时,需要大量重载方法

通配符

用在方法中,表示泛型可以接受任意类型的泛型类

只能取得类中数据,不能修改数据(因为类型不确定,无法设置类型)

:表示可以接收任意类型

格式:

方法声明(类名<?> 参数名){
方法体
}
package se.SE.practice;
class MyClass<T>{
    private T value1;

    public T getValue1() {
        return value1;
    }

    public void setValue1(T value1) {
        this.value1 = value1;
    }

    public <E> void MyMethod1(E t){
        System.out.println(t);
 }
}
public class Test{
    public static void main(String[] args) {
    MyClass myClass=new MyClass();
    myClass.setValue1(123);//设置value1的值为123
    print(myClass);
    }
    public static void print(MyClass<?> myClass){//通配符 传进来的myclass是什么类型 就在方法中定义什么类型
        myClass.getValue1();
    }
}

?extends类:

表示设置或者取得泛型上限

?extends Number

表示泛型必须是Number及其子类----也就是说?必须继承Number这个类

package se.SE.practice;
class MyClass<T extends Number>{
    private T value1;

    public T getValue1() {
        return value1;
    }

    public void setValue1(T value1) {
        this.value1 = value1;
    }

    public <E> void MyMethod1(E t){
        System.out.println(t);
 }
}
public class Test{
    public static void main(String[] args) {
    MyClass<Double> myClass=new MyClass();
    myClass.setValue1(78.3);//设置value1的值为78.3
    print(myClass);
    }
    public static void print(MyClass<? extends   Number> myClass){//通配符 
        myClass.getValue1();
    }
}
  • 用在类上:

T extends 类:

表示T必须是类或者类的子类

  • 用在方法上:

? extends 类:

表示只能接收类或者子类的泛型类,只能取得值不能修改值

(发生在父类到子类的向下转型,需要强转,由于具体子类不确定,因此无法强转)

? super 类:

只能用在方法中,取得泛型下限

eg?super String 表示只能取得String以及其父类,只能用于方法中

 public static void print(MyClass<? super  String> myClass){//通配符 
        myClass.getValue1("HELLO");//设置value1的值为HELLO
        myClass.getValue1();
    }

泛型的下限可以设置属性值,因为子类到父类自动的向上转型

泛型接口

泛型接口没有定义类型,子类实现接口有两种选择

  • 1子类继续保留泛型---子类还是泛型类

第一个T表示子类是泛型类,后面的T表示接口是泛型接口

class MyClass1Impl<T> implements IInterface<T> 
  • 2子类定义时确定好类型
class MyClass2Impl  implements IInterface<String>
package se.SE.practice;
interface IInterface <T> {//定义泛型接口IInterface
    T test(T t);
}
//子类实现接口继续保留泛型----子类还是泛型类
//class MyClass1Impl<T> implements IInterface<T> {
//    @Override
//    public T test(T t) {
//        return t;
//    }
//}
//子类实现接口定义类型-----子类定义了其他类型(本例中定义了String类)
class MyClass2Impl  implements IInterface<String>{
    @Override
     public String test(String s){
         return s;
        }
    }
public class Test {
    public static void main(String[] args) {
        IInterface<String> iInterface = new MyClass2Impl<String>() ;
        System.out.println(iInterface.test("Welcome to  my world!"));
    }
}

类型擦除

泛型信息仅存在于代码的源码编译阶段,进入JVM之前与泛型相关的信息会被擦除掉,也就是泛型擦除

java语法糖:

仅存在于源码编译阶段,编译后就消失不见-----典型:泛型/自动拆装箱/String常量的加号

作用:方便程序员的开发

 

通俗点讲:泛型类和普通类在java虚拟机内没有任何区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值