Java——泛型

Java 的泛型-(参数化类型)jdk1.8现在
泛型:(JDK1.5引入)指的就是在类定义的时候并不会设置类中的属性或方法中的参数的具体类型,而是在类使用时再进行定义。
泛型是jdk5引入的类型机制,就是讲类型参数化。java中的泛型,只在编译阶段有效。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型),也就是说在泛型使用过程中。
操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
Java 泛型的参数只可以代表类,不能代表个别对象。由于 Java 泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。Java 允许对个别泛型的类型参数进行约束,包括以下两种形式(假设 T 是泛型的类型参数,C 是一般类、泛类,或是泛型的类型参数):T 实现接口 I 。T 是 C ,或继承自 C 。一个泛型类不能实现Throwable接口。

1.新特性(jdk1.5)
从JDK1.0开始,几乎每个版本都会提供新特性。例如在JDK中有以下代表性版本:
JDK1.2: 推出了轻量级的界面包:Swing
JDK1.5: 推出新程序结构的设计思想。
JDK1.8: Lambda表达式、接口定义加强
现在已经接触了新特性:自动拆装箱、switch对String的支持

1.1可变参数
数组方法只能通过下标
(1)可变参数会自动包装成数组,使用时当做数组使用。
(2)当方法有多个参数时,可变参数放到参数列表最后。
(3)方法的可变参数,最多只能有一个。
(4)可变参数不传值时,只包装了一个空的数组。

1.2foreach循环:增强的for循环
将for循环转变为foreach循环:Alt+Enter
语法:(不需要知道数组下标)
for(数据类型 临时变量 : 数组(集合)) {
// 循环次数为数组长度,而每一次循环都会顺序取出数组中的一个元素赋值给临时变量
}

1.3静态导入(了解,不建议使用)
范例:定义MyMath类
package www.bit.java.util;
public class MyMath {
//静态方法
public static int add(int x, int y) {
return x + y;
}
public static int sub(int x, int y) {
return x - y;
}
}
//调用静态方法:类名.方法名

范例:使用MyMath类
package www.bit.java.test;
import www.bit.java.util.MyMath;
public class TestDemo {
public static void main(String[] args) {
System.out.println(MyMath.add(10, 20));
System.out.println(MyMath.sub(30, 10));
}
}

2.泛型
2.1泛型引入
希望编程时,及时发现类型不匹配的问题:
(1)必须明确知道参数类型中引用数据类的具体类型Object(类型)
(2)向下转型,需要通过instanceof判断

2.2泛型类的基本语法:
class MyClass {
T value1;
}

尖括号 <> 中的 T 被称作是类型参数,用于指代任何类型。实际上这个T你可以任意写,但出于规范的目的,Java还是建议我们用单个大写字母来代表类型参数。常见的如:
–T 代表一般的任何类。
–E 代表 Element 的意思,或者 Exception 异常的意思。
–K 代表 Key 的意思
–V 代表 Value 的意思,通常与 K 一起配合使用。
–S 代表 Subtype 的意思,文章后面部分会讲解示意。
使用泛型类:
MyClass myClass1 = new MyClass();
MyClass myClass2 = new MyClass();

注意:泛型只能接受类,所有的基本数据类型必须使用包装类!

范例:使用泛型定义Point类
使用泛型类的时候,决定属性的具体类型
package www.bit.java.test;
// T表示参数,是一个占位的标记;如果有多个泛型就继续在后面追加
class Point {
//x、y类型相同
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;
}
}

public class TestDemo {
public static void main(String[] args) {
// 设置数据
//JDK1.7泛型类实例化对象时构造方法调用这里<>不需要指定类型
//编译时解决具体类型
Point p = new Point<>() ;
p.setX(“东经80度”);
p.setY(“北纬20度”);
// 取出数据
String x = p.getX() ; // 避免了向下转型
String y = p.getY() ;
System.out.println(“x = " +x+”,y = "+y);
}
}

泛型的出现彻底改变了向下转型的需求!引入泛型后,如果明确设置了类型,则为设置类型;如果没有设置类型,则默认为Object类型。

2.3泛型方法
范例:泛型方法定义
class MyClass{
public void testMethod(T t) {
System.out.println(t);
}
}

泛型类与泛型方法没有关系。
泛型方法与泛型类稍有不同的地方是:类型参数也就是尖括号那一部分是写在返回值前面的。 中的 T 被称为类型参数,而方法中的 T 被称为参数化类型,它不是运行时真正的参数。
当然,声明的类型参数,其实也是可以当作返回值的类型的。

范例:泛型方法与泛型类共存
//泛型类
class MyClass{
//普通方法
public void testMethod1(T t) {
System.out.println(t);
}
//泛型方法
public E testMethod2(E e) {
return e;
}
}
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass<>();
myClass.testMethod1(“hello 泛型类”);
Integer i = myClass.testMethod2(100);
System.out.println(i);
}
}

泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准。
泛型类和泛型方法的参数最好分开写成不同的,不然容易混淆。
泛型类和泛型方法可以共存,二者各自独立。

**2.4通配符
在程序类中追加了泛型的定义后,避免了ClassCastException的问题,但是又会产生新的情况:参数的统一问题。
package www.bit.java.test;
class Message {
private T message ;

public T getMessage() {
    return message;
}

public void setMessage(T message) {
    this.message = message;
} 

}
public class TestDemo {
public static void main(String[] args) {
//如果现在泛型的类型设置的不是String,而是Integer.
Message message = new Message() ;
message.setMessage(55);
fun(message); //出现错误,不能接受String类型
}
// 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
public static void fun(Message<?> temp){
//temp.setMessage(100); 无法修改!
System.out.println(temp.getMessage());
}
}

泛型通配符:
“?”表示可以是任意类型,但是要求,不能对massage对象进行修改。
【? extends类:设置泛型上限】
例如:? extends Number,表示只能够设置Number或其子类,例如:Integer、Double等;
范例:观察泛型上限(常用)
package www.bit.java.test;
class Message { // 设置泛型上限
private T message ;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class TestDemo {
public static void main(String[] args) {
Message message = new Message() ;
message.setMessage(55);
fun(message);
}
// 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
public static void fun(Message<? extends Number> temp){
//temp.setMessage(100); 仍然无法修改!
System.out.println(temp.getMessage());
}
}

【? super 类:设置泛型下限】
例如:? super String,表示只能够设置String及其父类Object。
范例:设置泛型下限
package www.bit.java.test;
class Message {
private T message ;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class TestDemo {
public static void main(String[] args) {
Message message = new Message() ;
message.setMessage(“Hello World”);
fun(message);
}
public static void fun(Message<? super String> temp){
// 此时可以修改!!
temp.setMessage(“bit!”);
System.out.println(temp.getMessage());
}
}

注意:上限可以用在方法参数,类型,参数内容不能修改;而下限只能用在方法参数,可以修改内容!

2.5泛型接口
(1)泛型接口定义和泛型类区别不大
(2)泛型接口的实现类:
—泛型类(保留参数类型声明)
// 在接口上定义了泛型
interface IMessage {
public void print(T t) ;
}
class MessageImpl implements IMessage {
@Override
public void print(T t) {
System.out.println(t);
}
}

—不是泛型类(接口处制定具体类型)
// 在接口上定义了泛型
interface IMessage {
public void print(T t) ;
}
class MessageImpl implements IMessage {
@Override
public void print(String t) {
System.out.println(t);
}
}

范例:定义一个泛型接口
// 在接口上定义了泛型
interface IMessage {
public void print(T t) ;
}

2.6类型擦除
类型擦除:泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉。

通俗地讲,泛型类和普通类在 java 虚拟机内没有什么不同。

在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 则会被转译成普通的Object 类型,如果指定了上限如 则类型参数就被替换成类型上限。

泛型类型擦除:
(1)编译时的功能扩展,运行时擦除泛型信息
(2)如果泛型类型无上限类型,泛型擦除之后是Object
如果泛型类型有上限类型,泛型擦除之后的类型是上限类型

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值