Java范型随笔

最近在帝都好无聊啊, 排遣寂寞就只有让自己不要停下来,不断的思考了 QWQ;

最近做ndk, java有点忘了,突然看到了一些java范型方面的问题, 踌躇了一会, 想着想着,决定还是写个随笔记录下来。

范型语法这个网上找度娘可以要到一大把, 我就不记了, 主要是范型上下限问题。

案例:

public class Test {

  public static class Base{

  }

  public static class A extends Base{

  }

  public static class Fanxin<T>{

  T t;

  public T get(){

  return t;

  };

  public void set(T t){

  this.t = t;

  }

}

public static class B extends A{

}

  public static void main(String[] arvg){

    Fanxin<? extends Base> fanxin = new Fanxin<A>();

    Base a = fanxin.get();

    //fanxin.set(new A()); 1编译报错

    Fanxin<? super A> fanxin1 = new Fanxin<Base>();

    A obj = (A)fanxin1.get();

    //A obj = fanxin1.get(); 2编译报错

    //fanxin1.set(new Base());3编译报错

    fanxin1.set(new A());

  }

}

首先java范型我理解的是为了安全, 这样可以在编译期检测类型,而不会到运行的时候出现类型转化异常。 第一个 fanxin.set(new A());报错,是因为,这里类型是定义了上限,所以这里通配符代表的类型是base或者base的子类, 虽然A是base的子类, 但是这是不安全的,考虑这种情况:

Fanxin<B> fanxin = new Fainxin<B>();

......各种操作......

Fanxin<? extends Base> fanxin1 = fanxinB;

fanxin1.set(new A());

B b = fanxin.get();//这里有问题

这时候不安全的因素发生了,我们对fanxin1设置了一个对象A, 但是fanxin1实质是fanxin<B>对象, 这时候如果我们fanxin.get()获得的实际上是A对象,运行的时候会有类型转化异常。

这样是不安全的, 所以编译的时候会报错,如果一定要set, 那么可以强制类型转换来做,但是这样也失去了意义:

Fanxin<A> fanxinA = (Fanxin<A>)fanxin1;

fanxinA.set(new A());

第二个问题,通配符是A或者A的父类, 所以我们可以赋值, 面向对象的原则是子类可以替代父类, 所以是安全的。 但是如果我们读区值,然后赋值给其他对象,那么就会有问题, 比如;

Fanxin<Base> fanxinBase = new Fanxin<Base>();

Fanxin<? super A> fanxin1 = fanxinBase;   //Fanxin<? super A> fanxin = new Fanxin<? super A>();编译报错

A a =  fanxin1.get();

这里fanxin1.get()实际获得的是Base类, 赋值给A类,编译会报错, 运行的时候会有类型转化异常。

当然如果我们知道这个类的类型,那么我们也可以用强制类型转换避免编译报错。

例:

Base b = (Base) fanxin1.get();

总之 ?是范型里面的通配符,extends, super只是提供上下限的信息给编译起, 通配符有集合的概念在里面,Fanxin< ? extends Base>, ?类型可能是Base的任何子类,所以我们不能有赋值操作,因为子类和子类是不同的类型,只是子类可以替换父类而已,所以可以按父类来读取值, Fanxin<? super A>, ?类型是A的超类, 所以我们可以将A的任何子类赋值给他,这样是安全的,但是读取的时候,是无法知道这是什么类型的,但是java类都是Object类的扩展, 所以可以获取值赋给obj对象, Object obj = fanxin.get(); 如果要赋值给其他对象那么只有强制类型转换了。

时间: 2024-10-28 15:12:13

Java范型随笔的相关文章

JAVA范型-基础

JAVA范型-基础 一.泛型的概念 1.实现了参数化类型 2.用于编写可应用于多种类型的代码,即所编写的代码可应用于许多许多的类型. 3.范型容器.范型接口.范型方法都是经典的用法. 二.泛型与多态 1.多态是一种泛化机制.在使用类型说明的地方,使用多态确实具备一定的灵活性.但,多态是受限制的:只能接受基类或其子类(拘泥于单继承体系,使程序受限太多).而且,在实际编写代码时,只能使用已存在的基类或接口.同时,一旦指明了接口,程序就会要求你的代码必须使用特定接口(方法). 2.泛型:使我们能够编写

由Cannot create a generic array of ArrayList&lt;xx&gt;引出的学习--Java范型

最近在用Java写某个程序时希望写出一个包括ArrayList<xx>的数组 自己定义如下: ArrayList<edge>[] edges = new ArrayList<edge>()[10]; 然后编译器报错如下: Cannot create a generic array of ArrayList<edge>; 在C++里可以这样比较方便的定义:  vector<edge> a[100]; 在Java里报错,查询了一下,见已经有人在sta

java范型集合中的成员排序

范型集合中的类是JsonObject,不是自定义类,如果是自定义类就直接取要比较的字段值. 1 ArrayList<JSONObject> TList = new ArrayList<JSONObject>(); 2 3 for(int i=0;i<10000;i++) 4 { 5 JSONObject object=new JSONObject(); 6 Random rand = new Random(); 7 int randNum = rand.nextInt(200

Java 范型中的super和extends的区别

其实一句话就是: super最好用来作为输出参数,extends最好用来作为输入参数: 看看下面的例子: private class A { // } private class B extends A { // } private class C extends B { // } public void test() { List<? super B> test = new ArrayList(); test = new ArrayList<A>(); test = new Ar

Java范型之T extends Comparable&lt;? super T&gt;

在观察Java源码的时候,发现了这么一个写法T extends Comparable<? super T>.不禁纳闷为什么要这么写呢?有什么好处吗,extends和super在这里的作用着实让人有点不清楚. 接下来,我将结合代码跟大家分享一下我关于这里泛型应用的看法. 1.<T extends Comparable<? super T>>代表什么意思 大家可以明白的是这里应用到了Java的泛型,那么首先向大家说明一下这里extends的作用 extends后面跟的类型,

java 范型的那点事

1. 泛型概念 顾名思义,类型参数化(Generics) 2.未检查的类型转换 给一个原生类型赋值一个泛型类型 Box rawBox = new Box(); // rawBox is a raw type of Box<T> Box<Integer> intBox = rawBox; // warning: unchecked conversion 使用一个原生类型引用调用一个泛型类型引用的泛型方法时 Box<String> stringBox = new Box&l

Java千百问_05面向对象(014)_如何获取范型的类Class

点击进入_更多_Java千百问 1.如何获取范型的类Class java中,无法获取范型的类型,例如: public class Box<T> { public static void main(String[] args) { System.out.printf(T);//编译错误 } } 其实,由于java是强类型语言,在编译时我们并不知道T是什么具体类型,只有在编译后,不同场景指定之后才会知道,所以在编译前是无法获取T的类型.如果想获取T的类型,可以在泛型类中声明一个对象,通过对象获取当

分布式计算(一)基本范型

对于分布式的概念既模糊又有些理解,总是无法很好的把握,似乎与我们工作无关,但又天天在用,  究竟什么是分布式, 它能做什么?从那下手,网上可以查到很多,都使我越来越糊涂,大概是分布式计算.分布式存储.分布式缓冲等.日日梳理这些 模糊的东西,希望能有一天,能从这里走出一条光明的路. 1. 根据分布式计算抽象层次和封装层次的不同,可以将分布式的计算范型分为以下几类: 2.消息传递范型 消息传递(Message Passing) 范型利用网络API,完成将用户请求进行打包.传送和解包的工作,必要时还要

父类如何获取子类的范型

1,spring中一配置了<bean></bean>再启动项目的时候就会自动创建该类的实例. 2,java内存那块还得继续深入. 3,上代码: public class subParam extends param<myclass, myinvoke> {  //subParam 继承了param .param里面俩范型 public static void main(String[] args) throws Exception{ subParam  s = new