当前位置: 首页 > news >正文

免费网站注册免费创建网站凡科网可以免费做网站吗

免费网站注册免费创建网站,凡科网可以免费做网站吗,赣州网站建设信息,简历免费在线制作网站文章目录 1.为什么要有泛型 (Generic)1.1 泛型的概念1.2 使用泛型后的好处 2.在集合中使用泛型3.自定义泛型结构3.1 自定义泛型类、泛型接口3.2 自定义泛型方法 4.泛型在继承上的体现5.通配符的使用5.1 基本使用5.2 有限制的通配符的使用 1.为什么要有泛型 (Generic) Java中的… 文章目录 1.为什么要有泛型 (Generic)1.1 泛型的概念1.2 使用泛型后的好处 2.在集合中使用泛型3.自定义泛型结构3.1 自定义泛型类、泛型接口3.2 自定义泛型方法 4.泛型在继承上的体现5.通配符的使用5.1 基本使用5.2 有限制的通配符的使用 1.为什么要有泛型 (Generic) Java中的泛型就类似一个标签Label。比如在中药店每个抽屉外面贴着标签用于标记里面放的药材是什么。又比如在超市购物架上有很多瓶子每个瓶子装的是什么也有标签作标识。 泛型的设计背景 集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象所以在 JDK1.5 之前只能把元素类型设计为ObjectJDK1.5 之后使用泛型来解决。因为这个时候除了元素的类型不确定其他的部分是确定的例如关于这个元素如何保存如何管理等是确定的因此此时把元素的类型设计成一个参数这个类型参数叫做泛型。CollectionListArrayList 这个就是类型参数即泛型。 1.1 泛型的概念 所谓泛型就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时例如继承或实现这个接口用这个类型声明变量、创建对象时确定即传入实际的类型参数也称为类型实参。 从JDK1.5以后Java引入了“参数化类型Parameterized type”的概念 允许我们在创建集合时再指定集合元素的类型正如List这表明 该List只能保存字符串类型的对象。 JDK1.5改写了集合框架中的全部接口和类为这些接口、类增加了泛型支持从而可以在声明集合变量、创建集合对象时传入类型实参。 1.2 使用泛型后的好处 直接使用Object也可以存储数据那么为什么要用泛型呢 解决元素存储的安全性问题好比商品、药品标签不会弄错。解决获取数据元素时需要类型强制转换的问题好比不用每回拿商品、药品都要辨别。 在集合中没有泛型时 在集合中有泛型时 Java泛型可以保证如果程序在编译时没有发出警告运行时就不会产生 ClassCastException异常。同时代码更加简洁、健壮。 2.在集合中使用泛型 在这一部分我们来验证一下1.2节中提到的在集合中使用泛型所带来的好处。 首先来看一下在集合中没有使用泛型时的情况 //在集合中使用泛型之前的情况 Test public void test1(){ArrayList list new ArrayList();//需求存放学生成绩list.add(78);list.add(76);list.add(89);list.add(88);//问题一类型不安全list.add(kaixuan);for(Object score : list){//问题二强转时可能出现ClassCastExceptionint stuScore (Integer) score;System.out.println(stuScore);} }在上述代码块中我们声明了一个ArrayList对象listArrayList的本质对象引用的“变长”数组然后往里面添加了4个 int 类型的学生成绩和一个String类型的值kaixuan。但是这个时候并不会报编译错误因为现在list里面可以添加的是Object类型的因此就会出现前面提到的类型不安全的问题。接着我们去遍历一下 list 集合中的元素由于我们需要获取到的是 int 类型的值而 list 里面还存放有别的类型的数据因此需要强制类型转换。那么在这一步骤就有可能出现“类型转换异常”。 测试结果如下 可以看到提示 String类型不能强转成 Integer 类型。 接下来我们来看一下在集合中使用了泛型的情况以ArrayList为例。 Test public void test2(){//泛型是一个类型它不能是基本数据类型所以需要使用基本数据类型的包装类//下面的这个是标准的写法//ArrayListInteger list new ArrayListInteger();//jdk7新特性类型推断。 所以后面的泛型类型可以省略不写ArrayListInteger list new ArrayList();list.add(78);list.add(99);list.add(100);//编译时就会进行类型检查保证数据的安全。//list.add(dabing); //现在要添加的是一个String类型不是Integer类型的所以编译不通过//遍历方式一for(Integer score : list){//避免了强转操作int stuScore score;System.out.println(stuScore);}System.out.println(----------------------------------);//方式二IteratorInteger iterator list.iterator();while (iterator.hasNext()){int stuScore iterator.next();System.out.println(stuScore);} }上述代码块中我们首先声明了一个存放 Integer 类型数据的 ArrayList类的对象 list。而之所以可以这样声明是因为Java中的集合接口或集合类在 jdk5.0 时都修改为带泛型的结构。如下图所示 所以我们在实例化集合类时可以指明具体的泛型类型。指明完以后在集合类或接口中凡是定义类或接口时内部结构比如方法、构造器、属性等使用到类的泛型的位置都指定为实例化的泛型类型。比如add(E e) — 实例化以后add(Integer e)。 接着我们在 list 中添加了三个 int 类型的数据和一个String类型的数据dabing那么这个时候编译就会给出警告了因为我们指定了只能添加Integer类型的数据现在要添加的是一个String类型的。如下图所示 所以去除掉不符合要求的数据这一过程其实就是IDE帮我们做了一个类型检查。最后实现对 list 中的元素的遍历即可由于使用了泛型所以在遍历时就避免了强转的操作。我们以两种方式完成遍历增强 for 循环和 迭代器。 测试结果如下 注意点1.泛型的类型必须是类不能是基本数据类型。需要用到基本数据类型的位置拿包装类替换。 2.如果实例化时没有指明泛型的类型。默认类型为java.lang.Object类型。 3.自定义泛型结构 3.1 自定义泛型类、泛型接口 由于类和接口在声明上的相似性这里把自定义泛型类和自定义泛型接口放在一起讨论。 自定义泛型类的声明 interface ListT自定义泛型接口的声明 class GenTestK,V其中T,K,V 不代表值而是表示类型。这里使用任意字母都可以。 常用 T 表示是Type的缩写。 泛型类、泛型接口的实例化 一定要在类名后面指定类型参数的值类型。如 ListString strList new ArrayListString(); IteratorCustomer iterator customers.iterator();下面来看一个具体的例子 import java.util.ArrayList; import java.util.List;/* * 自定义泛型类 * */ public class OrderT { //这个T是什么类型现在还不知道实例化的时候才能知道所以这里当作是一个参数String orderName;int orderId;//类的内部结构就可以使用类的泛型T orderT;public Order(){}public Order(String orderName, int orderId, T orderT){this.orderName orderName;this.orderId orderId;this.orderT orderT;}public T getOrderT() {return orderT;}public void setOrderT(T orderT) {this.orderT orderT;}Overridepublic String toString() {return Order{ orderName orderName \ , orderId orderId , orderT orderT };}}在上述代码块中我们声明了一个名为 Order 的泛型类。由于在类名后加了所以Order 就是一个泛型类那么在该类的内部就可以使用这个泛型了。在 Order 类中声明了两个成员变量orderName 和 orderId同时声明了一个 T 类型的成员变量 orderT这个 T 是什么类型现在还不知道只有等到实例化 Order类 的时候才能知道。接着创建了该类的无参和带参的两个构造器注意到泛型类的构造器是不能加符号的创建格式如下 public GenericClass(){ }最后为orderT属性添加了get 、set方法重写了toString方法。 下面我们针对声明的泛型类 Order 做出一些测试首先做一下实例化操作创建两个Order类的对象。 Test public void test1(){//如果定义了泛型类实例化没有指明类的泛型则认为此泛型类型为Object类型不建议这样写//要求如果定义了类是带泛型的建议在实例化时要指明类的泛型。Order order new Order();order.setOrderT(123);order.setOrderT(ABC);System.out.println(order.getOrderT());//建议实例化时指明类的泛型 (且实例化的时候后面要补上)OrderString order1 new Order(orderAA, 1001, order:AA);order1.setOrderT(AA:hello);System.out.println(order1.getOrderT());}如果在实例化没有指明类的泛型则认为此泛型类型为Object类型 也就是类型会被擦除泛型对应的类型均按照Object处理但不等价于Object。如上述代码块中创建的order 对象由于实例化时没有指定泛型的结构所以在调用setOrderT()时可以传入任意类型的参数。但不建议不指定泛型结构的这种写法。所以一般我们要求如果定义了的类是带泛型的建议在实例化时要指明该类的泛型如上述代码块中创建对象order1 一样只要我们指定了具体的类型那么在后续的使用中编译器就会自动帮我们做类型的检查。如下图所示在指定了 T 为String 后在需要用到 T 的地方就自动给我们限定了是String 类型的了。 测试结果如下 下面我们来测试一下继承了泛型类的子类的实例化。 首先声明两个Order类的子类SubOrder 和 SubOrder1 SubOrder类的设计如下 public class SubOrder extends OrderInteger {//因为这个子类已经指明了泛型的结构所以SubOrder这个子类就不再是泛型类了}我们在 SubOrder 类中指定了泛型的结构所以SubOrder这个子类就不再是泛型类了。即SubOrder类名后就不要跟了而且在实例化SubOrder类时也不再需要指明泛型的类型只需把它当作普通类去实例化即可。 下面给出SubOrder的实例化测试 Test public void test2(){SubOrder sub1 new SubOrder();//由于子类在继承带泛型的类时指明了泛型类型则实例化子类对象时不再需要指明泛型。(也可以理解为此时的子类已经不是泛型类了)sub1.setOrderT(13);System.out.println(sub1.getOrderT().getClass().getName()); }可见在实例化时不再需要指明泛型。由于我们指定了SubOrder类中orderT的类型为Intgeger所以最后输出验证一下该成员变量的类型。 测试结果如下 SubOrder1类的设计如下: public class SubOrder1T extends OrderT{ //SubOrder1T仍然是泛型类 }在SubOrder1类中没有指明泛型的结构所以此时SubOrder1类还是一个泛型类。那么实例化的时候就需要像上述Order类那样实现了。下面给出测试程序 Test public void test2(){SubOrder1String sub2 new SubOrder1();sub2.setOrderT(order2....);System.out.println(sub2.getOrderT().getClass().getName()); }测试结果如下 此外关于泛型类和泛型接口还有一些别的规定。具体如下所示 泛型不同的引用不能相互赋值。 下面来做一下验证 Test public void test3(){//泛型不同的引用不能相互赋值ArrayListString list1 null;ArrayListInteger list2 null;list1 list2; //此处会报类型不兼容的错误 }错误信息如下 这是因为尽管在编译时ArrayList和ArrayList是两种类型但是在运行时只有一个ArrayList被加载到JVM中。 2. 如果泛型结构是一个接口或抽象类则不可创建泛型类的对象。 这是因为接口和抽象类本就是不能创建对象的。 3. jdk1.7时对泛型做了简化的操作 //1.7之前 ArrayListFruit flist new ArrayListFruit(); //1.7之后 ArrayListFruit flist new ArrayList(); 在类/接口上声明的泛型在本类或本接口中即代表某种类型可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。 我们在Order类中添加如下的静态方法show() //静态方法中不能使用类的泛型 public static void show(){System.out.println(orderT); }错误信息如下 这是因为静态结构早于对象的创建而泛型的指定在实例化的时候。所以在show方法创建的时候属性orderT还没有指定是什么类型的而且根本就没有出生这里可以借助java中静态方法中不能调用非静态变量来辅助理解。 5. 异常类不能是泛型的。 3.2 自定义泛型方法 方法也可以被泛型化不管此时定义在其中的类是不是泛型类也就是说泛型方法所属的类是不是泛型类都没有关系。 在泛型方法中可以定义泛型参数泛型参数与类的泛型参数没有任何关系。此时参数的类型就是传入数据的类型。 回顾一下在 Order 类中所定义的几个方法 public T getOrderT() {return orderT; }public void setOrderT(T orderT) {this.orderT orderT; }Override public String toString() {return Order{ orderName orderName \ , orderId orderId , orderT orderT }; }上述的三个方法都使用到了Order类的泛型但它们都不是泛型方法。 泛型方法的格式如下 [访问权限] 泛型 返回类型 方法名([泛型标识 参数名称]) 抛出的异常举例如下在Order类中添加一个泛型方法取名为copyFromArrayToList public E ListE copyFromArrayToList(E[] arr){ ArrayListE list new ArrayList();for(E e : arr) {list.add(e);}return list; }可以看到泛型方法头部的声明结构与普通方法的区别在于两点一是形参列表和返回值的类型处多了泛型结构二是在权限修饰符和返回值类型之间添加了泛型标识这是因为如果加 public 后面的,编译器会把形参位置“E[] arr”误认为是一个对象数组即数组元素为类E的对象但其实并没有名为 E 的类。 接下来我们来调用一下这个泛型方法 Test public void test4(){OrderString order new Order();Integer[] arr {1, 3, 4, 9};//泛型方法在调用时指明泛型参数的类型。这个类型和Order类的泛型没有任何的关系ListInteger list order.copyFromArrayToList(arr);System.out.println(list); }在实例化 Order 类的时候指明它的泛型结构为 String而在为泛型方法copyFromArrayToList() 指定形参的泛型时指定为 Integer所以再一次验证了泛型参数的类型与类的泛型没有任何的关系。 测试结果如下 此外泛型方法可以声明为静态的。因为泛型参数是在调用方法时确定的并非是在实例化类时确定。设计如下 public static E ListE copyFromArrayToList(E[] arr){ ArrayListE list new ArrayList();for(E e : arr) {list.add(e);}return list; }4.泛型在继承上的体现 如果 B 是 A 的一个子类型子类或者子接口而G是具有泛型声明的类或接口则G并不是G的子类型关系如下图所示 比如String 是 Object 的子类但是List 并不是List 的子类。 下面给出如下的测试 Test public void test1(){ListObject list1 null;ListString list2 null;//此时的lsit1和list2的类型不再具有父子类关系。//编译不通过// list1 list2; }此时语句 list1 list2 会编译不通过警告信息如下 这就是因为此时的 list1和list2 的类型不再具有父子类关系。 下面以反证法的角度解释一下为什么不能这样赋值。假设 list1 list2 可以实现那么现在往 list1中添加一个整形数据那么这样list2中就会混入非String的数据所以出错。 此外如果类A是类B的父类 G是具有泛型声明的类或接口则 A 是 B 的父类。 给出如下的测试 Test public void test2(){AbstractListString list1 null;ListString list2 null;ArrayListString list3 null;list1 list3;list2 list3;ListString list4 new ArrayList(); //这个的本质其实就是把list3赋给了list2 }测试结果如下 可以看到上述的操作是没有问题的。 5.通配符的使用 5.1 基本使用 通配符的符号? 若类A是类B的父类则G和G是没有关系的二者共同的父类是G? 比如 List?是List、List等各种泛型List的父类。 下面给出测试程序 Test public void test3(){ListObject list1 null;ListString list2 null;List? list null;list list1; list list2; }在上述代码段中List?是list1和list2的父类所以把list1和list2分别赋值给list是没有问题的编译通过。 接下来我们写一个参数为List?的函数这样的话list1和list2都应该能当作实参传进去。 //list1和list2都可以传进这个方法里 public void print(List? list){Iterator? iterator list.iterator();while(iterator.hasNext()){Object obj iterator.next();System.out.println(obj);} }由于在形参中使用了通配符所以在迭代器中也要用到最后获取的元素类型用Object接收。给出调用print方法的测试如下 Test public void test3(){ListObject list1 null;ListString list2 null;List? list null;list list1; //相当于List?是list1和list2的父类list list2;//编译通过print(list1);print(list2); }接下来尝试一个添加和读取的操作 Test public void test3(){ListObject list1 null;ListString list2 null;List? list null;ListString list3 new ArrayList();list3.add(AA);list3.add(BB);list3.add(CC);list list3;//添加对于List?就不能向其内部添加数据。//除了添加null之外。 因为什么类型的对象对可以赋值为nulllist.add(null);//读取 允许读取数据读取的数据类型为Object。Object o list.get(0);System.out.println(o);}在上述代码块中list3的类型为List,并向其中添加了三个字符串元素然后将list3赋值给list这样的话list和list3就指向同一片空间。那么这个时候就不能向List?内部添加数据因为添加的数据类型可能是非String的。 唯一的例外的是null它是所有类型的成员而对于读取元素则无限制因为list包含的元素总是一个Object。 测试结果如下 5.2 有限制的通配符的使用 通配符指定上限 上限 extends使用时指定的类型必须是继承某个类或者实现某个接口即。 通配符指定下限 下限super使用时指定的类型不能小于操作的类即 。 举例如下 下面给处测试验证 首先我们声明一个Person类并声明一个继承了Person类的Student类把他们用作泛型的类型。给出如下的测试程序 Test public void test4(){List? extends Person list1 null; //表示list1中的对象为 Person类型的List? super Person list2 null; //表示list2中的对象为 Person类型的ListStudent list3 new ArrayList();ListPerson list4 new ArrayList();ListObject list5 new ArrayList();list1 list3;list1 list4;//list5已经大于了Person了所以会报错// list1 list5;// list2 list3; //list3为小于Person的类型了所以会报错list2 list4;list2 list5; }显然三者之间的关系为Object是Person的父类Person是Student的父类。所以根据? extends Person的规则List 类型是不能传给List? extends Person的。同理list3也不能赋给list2。 错误信息如下 读取数据测试 Test public void test4(){List? extends Person list1 null; //表示list1中的对象为 Person类型的List? super Person list2 null; //表示list2中的对象为 Person类型的ListStudent list3 new ArrayList();ListPerson list4 new ArrayList();ListObject list5 new ArrayList();//读取数据list1 list3;Person p list1.get(0);//Student s list1.get(0); //编译不通过需要用Person类型接收找到的是Studentlist2 list4;Object obj list2.get(0);//Person ob list2.get(0); //编译不通过list2为大于等于Person的所以只能用Object对象来接收 }在接收数据时为了保证不出现问题需要用最大的类型去接收。因为在多态中子类可以赋给父类但父类不能赋为子类。 写入数据测试 Test public void test4(){ List? extends Person list1 null; //表示list1中的对象为 Person类型的 List? super Person list2 null; //表示list2中的对象为 Person类型的ListStudent list3 new ArrayList(); ListPerson list4 new ArrayList(); ListObject list5 new ArrayList();//写入数据 //编译不通过 //list1.add(new Student()); //虽然Student类型是小于Person的但是需要添加的类型可能比Student还小因为父类是不能赋给子类的//编译通过 list2.add(new Person()); list2.add(new Student()); //此处不报错是多态的体现}向list1中添加Student类的对象时会出错这是因为虽然Student类型是小于Person的但是需要添加的类型可能比Student还小那么像这样传参就会出现父类传给子类的现象。向list2中添加Person对象和Student对象都是可以的这是因为在list2的规定下Person类型确实是最小的而且Person都可以添加子类一定也是可以的。这其实都是多态的应用。
http://www.w-s-a.com/news/443717/

相关文章:

  • 梅州建站怎么做中国建设银行官网下载
  • 网站静态化设计广州网站备案方案
  • 西安网络技术有限公司网站扬中网站建设方案
  • 青海省教育厅门户网站wordpress core
  • idc科技公司网站模板蜜雪冰城网络营销案例分析
  • 微信与网站对接手机软件怎么做
  • 户县网站建设珠海专业制作网站
  • 麦当劳的网站优化建议猎头公司工作怎么样
  • 合肥地区网站制作网页浏览器打不开
  • 做网站的不给ftp网站如何做触屏滑动
  • wordpress statraq重庆百度优化
  • 企业网站官网英文WordPress站点切换为中文
  • 服装公司网站定位一点号自媒体平台
  • 密云微网站建设汽车之家手机官网首页
  • 多语言外贸网站制作苏州建设网站微信公众号
  • 用wordpress建站学什么百度给企业做网站吗
  • 福建城乡建设网站做数码测评的网站
  • 东海县建设局网站wordpress 好用的主题
  • 网站图片设计制作制作一个门户网站需要多少钱
  • 虚拟币交易网站源码自己给网站做支付接口
  • 免费的seo网站在线 crm
  • 绍兴市高速公路建设指挥部网站网站主页和子页风格如何统一
  • 获取网站状态网站租金可以做办公费吗
  • 网站开发执行什么标准号wordpress主题 表白
  • 杭州网站推广与优化凡科网是免费的吗
  • 公司网站的重要性门户网站推广介绍方案
  • 做金融网站看那些素材江门网红打卡景点蓬江区
  • 饮食网站模板建网站中企动力优
  • 郑州 制造 网站东平企业建站公司
  • 天津设计师网站大全展示型网站搭建