JavaSE笔记(2.5)Java基础

您所在的位置:网站首页 java返回list泛型 JavaSE笔记(2.5)Java基础

JavaSE笔记(2.5)Java基础

2023-03-24 21:36| 来源: 网络整理| 查看: 265

前言

记录学习过程 泛型是一个很重要的知识点 其实用过集合就都对泛型有一定的了解

目录泛型泛型的特点泛型的使用继承泛型类通配符通配符相关类型擦除总结

泛型

泛型:把明确数据类型的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型 Java泛型设计原则:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常

相关术语:

ArrayList中的E称为类型参数变量ArrayList中的Integer称为实际类型参数整个称为ArrayList泛型类型整个ArrayList称为参数化的类型ParameterizedType

泛型是在jdk1.5引进的,jdk1.5以前往列表添加数据:

List list=new ArrayList(); list.add("a"); list.add(1); for(int i=0;i private T classId; private E className; public MyClass(T classId, E className) { this.classId = classId; this.className = className; } public T getClassId() { return classId; } public void setClassId(T classId) { this.classId = classId; } public E getClassName() { return className; } public void setClassName(E className) { this.className = className; } @Override public String toString() { return "MyClass{" + "classId=" + classId + ", className=" + className + '}'; } }

可以看出MyClass类没有定义数据类型,这样就可以很方便的使用 创建一个测试类:

package com.company.javaBasis; import com.company.entity.MyClass; public class TestMyClass { public static void main(String[] args){ MyClass myClass=new MyClass(1,"Java"); System.out.println(myClass.toString()); MyClass myClass1=new MyClass("JavaScript",2); System.out.println(myClass1.toString()); } }

在这里插入图片描述

可以看出使用了泛型后,根据用户的想法,想怎么改类型就怎么改

需要注意:

(1)实例化泛型类时,必须指定E和T的具体类型,比如这里指定的是Integer和String

(2)指定的具体类型必须是类,不能是int,float等这些基础类型

(3)不能对泛型类使用instanceof。为什么呢?这是因为泛型类只在编译期有效,在运行时期不区分是什么类型。

例:在这里插入图片描述

泛型接口

泛型定义到接口上就是泛型接口 泛型接口:

package com.company.javaBasis; public interface SayHello { //这是一个普通的方法,不是泛型方法 public void say(T t); }

测试类:

package com.company.javaBasis; public class TestSayHello implements SayHello{ @Override public void say(String string) { System.out.println("hello,"+string); } public static void main(String[] args){ TestSayHello testSayHello=new TestSayHello(); testSayHello.say("zhangsan"); } }

在这里插入图片描述

需要注意:

(1)继承泛型接口的时候就需要指定具体是什么类型

(2)泛型中的方法也需要对相应的泛型参数赋予具体的类型。

泛型方法

只在某个方法上使用泛型,即我们只关心这个方法,对他的类不做要求 泛型方法:

package com.company.javaBasis; public class TestSayHello implements SayHello{ //带返回值泛型方法 public T sayBye(T t){ return t; } //无返回值泛型方法 public void sayBye1(T t){ System.out.println("Bye,"+t); } @Override public void say(String string) { System.out.println("hello,"+string); } public static void main(String[] args){ TestSayHello testSayHello=new TestSayHello(); testSayHello.say("zhangsan"); //测试泛型方法 String str=testSayHello.sayBye("Bye"); System.out.println(str); testSayHello.sayBye1("zhangsan"); } }

在这里插入图片描述

泛型标志< T >在权限修饰符后

继承泛型类

泛型类是拥有泛型这个特性的类,它本质上还是一个Java类,那么它就可以被继承

所以继承泛型类就可以分成两种:

子类明确泛型类的类型参数变量

子类不明确泛型类的类型参数变量

也就是在子类选择要不要明确数据类型

子类明确泛型类的类型参数变量

刚才的泛型接口就是子类明确泛型类的类型参数变量在这里插入图片描述

在继承implements里已经确定了类型参数变量< String >

子类不明确泛型类的类型参数变量

编写一个子类继承SayHello接口,并且不明确类型参数变量

package com.company.javaBasis; public class TestSayHelloNoSure implements SayHello { @Override public void say(T t) { System.out.println("Say "+t); } public static void main(String[] args){ TestSayHelloNoSure testSayHelloNoSure=new TestSayHelloNoSure(); testSayHelloNoSure.say("hello"); } }

可以看出继承泛型类和继承普通类一样,,只有看用户要不要确定类型参数变量< T >

通配符

当我们不清楚泛型究竟是什么类型,但又必须要用时 例如一个类,输入的参数是List类型

没有学泛型:

public void MyList(List list){ for(int i=0;i for(int i=0;i for(int i=0;i }

通配符:

public static void test(List list) { }

如何选择?

原则:

如果参数之间的类型有依赖关系,或者返回值是与参数之间有依赖关系的。那么就使用泛型方法如果没有依赖关系的,就使用通配符,通配符会灵活一些.

把一个对象分为声明、使用两部分的话 泛型侧重于类型的声明上代码复用,通配符则侧重于使用上的代码复用。 泛型用于定义内部数据类型的不确定性,通配符则用于定义使用的对象类型不确定性

类型擦除

前面有反射得出了:泛型只在编译期有效,在运行期虚拟机是分辨不出来的 也就是在编译期Java编译期将泛型擦除了

创建两个同名参数类型不同的方法:

public void MyList(List list){ for(int i=0;i for(int i=0;i public static void main(String[] args){ try { Class myclass=Class.forName("com.company.javaBasis.SayHello"); Method[] methods=myclass.getMethods(); for(Method method:methods) System.out.println(method.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }

在这里插入图片描述

是Object对象,这就是最初没有泛型时,都是使用Object类型表示所有类型

之前的类型擦除,都是直接擦除到Object,如何限制擦除到一定程度? 使用边界,让编译期擦除到边界就不擦除了

interface A{ void testA(); } interface B{ void testB(); } public class TestGeneric { public static class Test{ private T val; public Test(T val){ val = val; } public void test(){ val.testA(); val.testB(); } } }

编译成功,因为声明了Test必须具有类型A与B 所以就可以安全的使用A的testA方法和B的testB方法,不必担心类型擦除后没用

public static class Test{ private T val; public Test(T val){ val = val; } public void test(){ val.testA(); val.testB(); } }

在这里插入图片描述

当然,编译期会报错 类型擦除如果指定了类型参数的上界的话,则使用这个上界

总结

泛型是一个语法糖,语法糖就是一个方便程序员的功能,对语言没有任何影响 使用泛型可以提升代码的复用 学习过程跟随大佬的脚步 泛型就是这么简单 深入理解Java中的泛型 类型擦除详解



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3