java泛型、泛型类及特点、限制泛型、类型通配符声明、泛型方法

java泛型:

  • 泛型简介
  • 泛型类
  • 限制泛型可用类型
  • 类型通配声明
  • 泛型方法

问题: 如果我们需要产生多个对象,每个对象的逻辑完全一样,只是对象内的成员变量的类型不同。那我们该如何去做?如果按照正常的做法就要创建多个类文件,给每个类中的成员变量设置指定的数据类型。这样做的缺点: 这样会导致类膨胀,重用太差。解决方法: 创建一个类文件,给这个类中2成员变量设置Object(是所有类的父类)数据类型。 缺点: 编译的时候正常,但运行的时候可能会出现异常。因为Object导致整个类对变量的属性很模糊。面对这样的问题在JDK1.5以后引入泛型

class Cla1
{Object a;public Cla1(Object a) {this.a=a;}public Object getData(){return a;}
}
//class cla2
//{
//	String a;
//	public cla2(String a) {
//		this.a=a;
//	}
//	public String getData(){
//		return a;
//	}
//}
public class Mian {public static void main(String[] args) {Cla1 c1=new Cla1("String");System.out.println(c1.getData());//System.out.println((Integer)c1.getData());Object导致整个类对变量的属性很模糊,在强制类型转换的时候会出现下列错误//Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer//at Mian.main(Mian.java:25)}
}

泛型简介:

  • 泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动的和隐式的。
  • 泛型的原理就是 类型的参数化,即把类型看做参数。也就是说把所有要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。
  • 简单的说,类型变量 扮演的角色就如同一个参数,它是提供给编译器用来类型检查的信息。
  • 泛型可以提高代码的扩展性和重用性。
class Cla1<T>//T必须是引用类型
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
public class Mian {public static void main(String[] args) {Cla1<Integer> c1=new Cla1<Integer>(10);//<Integer>明确类中参数的类型,相当于类型的参数化,用<>表示//Cla1<int> c1=new Cla1<int>(10);这样写会报错,<>括号内的必须是引用类型,System.out.println(c1.getData());}
}

泛型类及特点:

  • 泛型的类型参数可以是泛型类
  • 泛型类可以同时设置多个类型参数
  • 泛型类可以继承泛型类
  • 泛型类可以实现泛型接口

泛型类可以同时设置多个类型参数

class Cla1<T> //一个类型参数
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
class Cla2<T1,T2> //多个类型参数
{T1 a;T2 b;public Cla2(T1 a,T2 b) {this.a=a;this.b=b;}public T1 getDataA(){return a;}public T2 getDataB(){return b;}
}
public class Mian {public static void main(String[] args) {Cla1<Integer> c1=new Cla1<Integer>(10);System.out.println(c1.getData());Cla2<Integer,String> c2=new Cla2<Integer,String>(30,"输出");System.out.println(c2.getDataA());System.out.println(c2.getDataB());System.out.println(c2.getDataA()+c2.getDataB());//数字和字符串相加,+起连接作用Cla2<Integer,Integer> c3=new Cla2<Integer,Integer>(100,120);System.out.println(c3.getDataA());System.out.println(c3.getDataB());System.out.println(c3.getDataA()+c3.getDataB());//数字和数字相加,+就是数值相加											    //有的博客说这里的数值不能直接相加		}
}

泛型类型可以是泛型类:

class Cla1<T> //一个类型参数
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
public class Main {public static void main(String[] args) {Cla1<Cla1<Integer>> c1=new Cla1<Cla1<Integer>>(new Cla1<Integer>(10));//泛型类里面的类型还是泛型类,传参的时候传的是泛型类的引用System.out.println(c1.getData().getData());//c1.getData()是调用的当做参数传入的泛型类,Cla1<Integer> a,就相当于这样的//此时a是泛型类类型,需要再对a取内容才能得到真正的a的数值,也就是当做参数传进去的那个泛型类的构造方法的数值}
}

泛型类可以继承泛型类:

abstract class Cla1<T> //一个类型参数
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}abstract void printInfo();
}
class Cla2<T,T2> extends Cla1<T> //Cla2继承Cla1同时还可以增加泛型的个数,这里增加了T2
{T2 b;public Cla2(T a,T2 b) {super(a);this.b=b;}public T2 getDataB(){return b;}@Overridevoid printInfo() {//如果这个类也是抽象类的话,就不用在将父类里面的抽象方法给补全了System.out.println("继承的类是泛型抽象类,所以要在子类里面实现抽象方法的方法体");}
}
public class Main {public static void main(String[] args) {	Cla2<Integer,String> c2=new Cla2<Integer,String>(110,"String");System.out.println(c2.getData());System.out.println(c2.getDataB());c2.printInfo();}

泛型类可以实现继承泛型接口:

interface Cla1<T>
{abstract void printfInfo(T t);//在接口中public和abstract可以省略,默认就是public和abstract
}
class Cla2<T> implements Cla1<T>
{public void printfInfo(T t){System.out.println("泛型类继承泛型接口");}
}
public class Main {public static void main(String[] args) {Cla2<String> c1=new Cla2<String>();c1.printfInfo("");}
}

限制泛型可用类型:

  • 在定义泛型类别的时候,默认在实例化泛型类的时候可以使用任何类型,但是如果要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类或者实现某个接口。例如:class Cla11<T estends Move>这里Move是接口interface move这就要求T是接口Move类型的。接口是一个模版,需要类来继承这个接口来实现才能实例化,所以说继承了Move这个接口的类都属于T extren Move。这里就要求是继承了Move接口的类的类型。class Cla1<T extends Animal>这里Animal是自己定义的一个类,那么T extends Animal表示T只能是Animal类型或者其子类类型。
  • 当没有指定泛型继承的类型或者接口时,默认使用extends Object,所以默认情况下任何类型都可以作为参数传入。

限制使用泛型类型,只能用某个特定类型或者是其子类型才能实例化该类型:

interface Cla1<T extends String>
{abstract void printfInfo(T t);//在接口中public和abstract可以省略,默认就是public和abstract
}
class Cla2<T extends String> implements Cla1<T>//限制泛型只能用某个特定类型或者是其子类型使用extends继承,限制使用泛型类型为String类型
{T str;public Cla2(T str) {this.str=str;}public void printfInfo(T t){System.out.println(str);System.out.println("泛型类继承泛型接口");}
}
class Cla3<T extends String,T2 extends Integer > extends Cla2<T>
{T2 in;public Cla3(T str,T2 in) {super(str);this.in=in;}public void printfInfo(T t){System.out.println("父类:"+str+" 子类:"+in);}
}
public class Main {public static void main(String[] args) {Cla2<String> c1=new Cla2<String>("父类");c1.printfInfo(" ");Cla3<String,Integer> c2=new Cla3<String,Integer>("子类",10);c2.printfInfo(" ");}
}

类型通配符声明:

  • 同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。
  • 泛型类实例之间的不见兼容性会带来使用的不方便。我们可以使用泛型通配符<?>声明泛型类的变量就可以解决这个问题。
  • 和限制泛型的上限相似,同样可以使用extends关键字限定通配类型的上限:<? extends 为某种类型>比如:<? extends String>
  • 还可以使用super关键词将通配符匹配类型限定为某个类型及其父类型
class Animal
{}
class Dog extends Animal
{}
class Cla1<T>
{T a;public Cla1(T a) {this.a=a;}T getData(){return a;}
}
public class Main {public static void main(String[] args) {Cla1<String> c1=new Cla1<String>("String");System.out.println(c1.getData());Cla1<Double> c2=new Cla1<Double>(1.23);System.out.println(c2.getData());//c1=c2;不允许这样会报错,因为不是一个类型的Cla1<?> c3;//使用通配符,即可不用限制类型c3=c1;c3=c2;Cla1<? extends String> c4;c4=c1;//c4=c2;因为限制了为String类型所以会报错Cla1<Dog> c5=new Cla1<Dog>(new Dog());Cla1<Object> c7=new Cla1<Object>(new Object());Cla1<? super Dog> c6;//使用super关键词将通配符匹配类型限定为某个类型及其父类型,c6必须是Dog的父类c6=c5;Cla1<? super Animal> c8;c8=c7;}
}

泛型方法:

  • 不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。其定义格式为:访问修饰符 <泛型列表> 返回类型 方法名(){}
  • 在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明。
  • 类中的其他方法不能使用当前方法声明的泛型。
  • 泛型方法更加灵活,它可以不受泛型类的约束。比方法重载更加灵活。
  • 提示: 是否拥有泛型方法,与其所在的类是否是泛型类没有关系,要定义泛型方法,只需要将泛型参数列表置于返回值前。
  • 什么时候使用泛型方法,而不是泛型类呢? 添加类型约束条件只作用于一个方法的多个参数之间、而不涉及到类中的其他方法时。 施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数。
  • 注意: 同样泛型方法也可以对齐进行限制和在泛型类里面的限制一样。T在编译的时候会重置为该类型在类中声明是所继承的父类。比如:<T> T printInfo(T t)T默认是继承Object的,所以在编译的时候会重置为Object,而<T extends Animal>在编译的时候会重置为Animal。
class Animal
{void eat(){System.out.println("动物吃");}
}
class Dog extends Animal
{void eat(){System.out.println("狗啃骨头");}
}
class A<T>
{void printInfo(T t){System.out.println(t);}
}
class B
{<T> T printInfo(T t){//T仅对本方法有效,可用于该方法的返回类型声明和该方法的参数类型声明T a;//可用于方法代码中的局部变量的类型声明System.out.println(t);return t;}<T,T2> void printInfo(T t,T2 t2){//一个泛型方法有多个泛型参数,这也是个泛型方法的重载//System.out.println(t+t2);这样写不允许,必须分开写,因为还没有实例化,类型不确定,不能相加System.out.println(t);System.out.println(t2);}<T extends Animal> void printInfo2(T t)//施加泛型方法的类型约束{t.eat();}static <T extends Animal> void printInfo3(T t)//施加泛型方法的类型约束{t.eat();}
}
public class Main {public static void main(String[] args) {A<String> a=new A<String>();a.printInfo("String");B b=new B();b.printInfo("String");b.printInfo('c');b.printInfo(1213);b.printInfo(1,"str");b.printInfo2(new Dog());b.printInfo2(new Animal());B.printInfo3(new Animal());B.printInfo3(new Dog());//静态方法本身就是和类是脱离的,可以直接通过类名来调用静态方法}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不生效 设置了viewport_配置viewport

最近项目中需要开发内嵌的H5页面&#xff0c;viewport不是很熟悉&#xff0c;故来翻译一下此篇文件加深理解原文配置viewportIOS上的safari使用一种缩放的工作模式来展示pc端的网页&#xff0c;如果默认的设置对你的网页展示不友好&#xff0c;推荐你改变veiwport默认配置&…

Linux文件操作实用笔记

Linux系统遵循一切皆是操作文件的规则。所以想用好Linux系统&#xff0c;就必须要掌握文件相关的操作。 1、创建文件命令&#xff1a;touch 语法格式&#xff1a; touch filename #filename 文件名称。 比如 touch hello.txt就会在当前木创建一个hello.txt的文件。 说明&#x…

安装完CentOS 7 后必做的七件事

CentOS是最多人用来运行服务器的 Linux 版本&#xff0c;最新版本是 CentOS 7。当你兴趣勃勃地在一台主机或 VPS 上安装 CentOS 7 后&#xff0c;首要的工作肯定是加强它的安全性&#xff0c;以下列出的七件事&#xff0c;是你进一步配置系统和安装其他软件前必须做的。 1. 更改…

python显示小数点后几位数_python窗口编程-3:数位处理(整数)

我们在上一次课程中(python窗口编程-2&#xff1a;风格与布局 )&#xff0c;制作了完整的计算器窗口界面&#xff0c;只是那个窗口没有真正的功能&#xff0c;是点击任何按钮都会关闭。这一次&#xff0c;我们加入一些事件处理的功能&#xff0c;让它成为一个正常工作的窗口程序…

Linux文件目录基础笔记

1、进入目录名称&#xff1a;cdcd命令主要是方便用户切换到不同目录的指令。比如&#xff1a;cd #只执行cd命令默认进入root的根目录cd /home #进入home目录&#xff0c;如果home目录有testdir目录的话&#xff0c;可以执行 cd testdir 进入testdir目录。2、创建目录命令&#…

eclipse安卓工程的构建、配置连接模拟器、安卓工程结构介绍

安卓工程构建及第一个安卓程序运行&#xff1a; 首先新建安卓工程&#xff1a; 然后填写APP信息&#xff0c;下面的包名一般都是公司域名的倒写&#xff0c;包名中不能有中文&#xff0c;否则会报错。 然后配置一些安卓app的选项 有关app启动的图标&#xff08;就像QQ的企鹅一…

android eclipse 导入idea项目

将以下代码复制到.project中 <?xml version"1.0" encoding"UTF-8"?> <projectDescription> <name>IDEATest</name> <comment/> <projects/> <buildSpec> <buildCommand> <name>com.android.ide.…

Linux中su和sudo的用法整理

一、为什么会有su和sudo命令&#xff1f;主要是因为在实际工作当中需要在Linux不同用户之间进行切换。root用户权限最高很多时候需要root用户才能执行一些关键命令。所以需要临时切换为root用户。工作完成后&#xff0c;考虑到系统的安全性避免误操作需要切换为普通用户。su和s…

codeforces 650B - Image Preview

题意&#xff1a;给你n个照片&#xff0c;从第一个照片开始看&#xff0c;如果一张照片是w&#xff0c;那么要花费b时间去反转他&#xff0c;否则不用反转&#xff0c;看一张从来没看过的照片要1时间&#xff0c; 从一张滑动到另一张要a时间。如果一张照片看过&#xff0c;则不…

asp js单步调试_如何使用Chrome的控制台高效的调试Javascript代码?

引言在我们的日常开发中我们常常会遇到JavaScript的调试问题&#xff0c;而我们解决问题的传统解决方案就是使用大量的console.log或者console对象的其他方法&#xff0c;这会给我们带来很多不便&#xff0c;特别是遇到复杂问题的时候&#xff0c;可能会出现大量的console.log&…

安卓App的启动过程、安卓布局分类及布局和页面的关系

Android App 启动流程: 当你想要启动一个app时&#xff0c;首先得点击该app桌面图标。那点击图标时到底发生了什么呢&#xff1f;先看个理论知识 .Launcher: launcher其实就是一个app&#xff0c;从功能上说&#xff0c;是对手机上其他app的一个管理和启动&#xff0c;从代码…

Linux文件默认权限和umask笔记

关于Linux文件默认权限的问题&#xff0c;可以实际先尝试一下如下命令&#xff1a;root用户登录[rootlocalhost test]# touch file1[rootlocalhost test]# ls-l file1-rw-r--r-- 1 root root 0 May 5 08:28 file1 #输出结果 对应的数字权限 644[rootlocalhost test]# touch fi…

Android相对布局(RelativeLayout)常用属性、练习使用按键、文本框等控件、线性布局(LinearLayout)属性

RelativeLayout中子控件常用属性&#xff1a; 子控件默认是从父控件的左上角开始排列的 相对于父控件 android:layout_alignParentTop"true" 和父控件的顶部对齐android:layout_alignParentBottom"true" 和父控件的底部对齐android:layout_alignPar…

Seata AT模式

基本思路 先决条件 支持本地ACID事务的关系数据库。通过JDBC访问数据库的Java应用程序。 整体机制 从两个阶段提交协议的演变&#xff1a; 阶段1&#xff1a;在同一本地事务中提交业务数据和回滚日志&#xff0c;然后释放本地锁和连接资源。阶段2&#xff1a; 对于提交情况…

自媒体各大平台收益对比_哪些自媒体平台没有新手期,适合小白撸收益?

2-26把我设置为星标&#xff0c;不错过每一次的干货&#xff5e;各大自媒体平台的新手期总是让小白们望而却步&#xff0c;特别是百家号审核非常严格&#xff0c;如果没思路、没人指导&#xff0c;过新手有难度。不过&#xff0c;还是有很多平台对新手宝宝很友好&#xff0c;没…

Linux关于文件的权限笔记

1、调整文件的权限命令&#xff1a;chmodLinux的每个文件都定义了文件的拥有者&#xff1a;u(user)、拥有组&#xff1a;g&#xff08;group&#xff09;、其他人&#xff1a;o&#xff08;others&#xff09;权限&#xff0c;对应的权限用rwx的组合来定义。使用chmod命令&…

presentViewController和pushViewController

iPhone开发中从一个视图跳到另一个视图有三种方法&#xff1a;1、self.view addSubView:view 、self.window addSubView,需要注意的是&#xff0c;这个方法只是把页面加在当前页面。此时在用self.navigationControler.pushViewController和 pushViewController 是不行的。要想使…