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

珠海做网站需要多少钱微信公众号的模板网站

珠海做网站需要多少钱,微信公众号的模板网站,重庆公司章程电子版在哪里下载,对网站建设展望作为一个 Java 程序员#xff0c;用到泛型最多的#xff0c;我估计应该就是这一行代码#xff1a; ListString list new ArrayList();这也是所有 Java 程序员的泛型之路开始的地方啊。 不过本文讲泛型#xff0c;先不从这里开始讲#xff0c;而是再往前…作为一个 Java 程序员用到泛型最多的我估计应该就是这一行代码 ListString list new ArrayList();这也是所有 Java 程序员的泛型之路开始的地方啊。 不过本文讲泛型先不从这里开始讲而是再往前看一下看一看没有泛型的时候Java 代码是怎么写的然后我们才会知道为什么要加入泛型泛型代码该怎么写。 这里插播一下我的微信公众号希望大家能够多多关注我会不定期更新优秀的技术文章 接下来开始我们的正文。 为什么要设计泛型 提高代码重用性 没有泛型之前我们写一个两数相加的函数 public static int add(int a, int b) {return a b; }看似没问题对吧。不过这个时候我们想计算 float 类型的加法那这个函数就不行了因为他只能计算 int 值。此时就只能再加入一个相同的函数了 public static float add(float a, float b) {return a b; }现在我们有两个方法能够计算 int 和 float 类型的加法。那现在如果要计算 String 类型的加法呢这两个方法就又不够用了。面对这样的需求在没有泛型的支持下我们只能不断地增加逻辑基本相同的方法代码重用性极低。 这就是泛型要解决的第一个问题提高代码重用性。 那在泛型的加持下我们如何编写这个函数呢 public static T extends Number double add(T a, T b) {return a.doubleValue() b.doubleValue(); }这个方法使用了泛型它能够处理任何类型的数字相加不需要针对每个类型编写各自的加法方法。这就大大提高了代码的重用性有了这个方法那些固定类型的方法就都可以删了。 特别是一些逻辑相同的代码使用泛型不仅能够提高代码重用性还能够提高可读性。比如说下面这段代码真是的是非常好用 public static T void printArray(T[] array) {for (T element : array) {System.out.println(element);} }泛型的这个特性虽然很牛了但是这还不是 Java 要设计泛型的全部原因。因为泛型还有一个作用那就是保证类型安全。 保证类型安全 在说泛型的这个作用之前先问大家一个问题咱们常用的集合 ArrayList 是 Java 哪个版本加入的呢泛型又是 Java 哪个版本加入的呢 答案ArrayList 是 Java 1.2 版本加入的而泛型是 Java 1.5 加入的。 也就是说有一段时时间ArrayList 不是大家普遍认识的带泛型的 ArrayListT 这种形式而是一个只能存放 Object 的列表。 在那一段泛型之光没有照耀到 Java 的日子里保证类型安全成为了 Java 程序员在使用集合时不得不考虑的事情考虑下面这一段代码 ArrayList list new ArrayList(); list.add(123); // do some work...... Integer num (Integer) list.get(0);这段代码没有使用泛型来使用 ArrayList我们加入了字符串 123但是在使用时我们假定程序员忘记了加入的类型他只记得好像应该是数字于是在获取时就直接使用了 Integer 类强转。 这样的代码是能通过编译的但是在运行的时候会崩溃 Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer这是一个典型的未使用泛型而导致的类型安全无法保证引发的崩溃。让程序员去保证类型安全本身是不靠谱的做法特别是在这种都是 Object 对象的列表中鬼都不会知道存着的是个什么鬼。 这个时候就需要泛型出场了泛型能够在编译时保证类型安全。例如上面的代码我们加入泛型 ArrayListString list new ArrayList(); list.add(123); Integer num (Integer) list.get(0);首先ArrayList 加入泛型后我们就知道这个列表是只能存入 String 类型的也就不会将其转换为 Integer。那如果我非要转换呢javac 编译器就会报错 错误: 不兼容的类型: String无法转换为IntegerInteger num (Integer) list.get(0);这样类型安全就可以在编译时得到保证不会出现在运行时的崩溃。 例子的代码很简单大家可能看不到这一点对于软件开发有多重要在大型复杂的项目中这种类型安全的保证是能减少很多运行时的崩溃的。特别是一般像这种类型不一致的崩溃很多都是偶现的偶现的 BUG 是最恶心的因此使用泛型保证类型安全是十分必要的。 消除强制类型转换 泛型的这个作用其实就是上面保证类型安全这一点带来的。没有用泛型时需要我们使用强制类型转化但是加入泛型后编译器已经能够知道我们存入的是什么类型因此也就不需要我们进行强制类型转换了。 既然泛型有那么大的作用那我们就赶紧把泛型用起来吧。 使用泛型 这一节我们来看看如何使用系统提供的泛型类以及其中需要注意的事项。 最常用到泛型的地方便是集合了使用这些泛型集合类时只需要把具体泛型参数 T 替换为需要的类型即可例如 ArrayListString、ArrayListNumber、 MapString, Integer 等。 如果在使用泛型类时不指定类型参数编译器会给出警告且只能将 T 视为 Object 类型。这个时候就需要程序员自己去保证类型安全了因此强烈不建议这么做因为这样容易将类型转换异常带到运行时中去。 使用泛型基本就需要注意以上两点下面介绍一下在使用泛型时的注意事项这也是大家很少关注到的向上转型的问题。 在 Java 中ArrayListT 是实现了 ListT 接口也就是说它可以向上转型为 ListT public class ArrayListE extends AbstractListEimplements ListE, RandomAccess, Cloneable, java.io.Serializable那么问题就来了当泛型参数不同时还能向上转型么说具体一点ArrayListString 能转型为 ListNumber 么 答案是不行的 ArrayList List new ArrayListString(); //Raw use of parameterized class ArrayList ListInteger list new ArrayListString(); //直接报错为什么 Java 不允许这么转型呢因为运行转型的话那么对于一个 ArrayListString 的容器我将其转型为 ArrayListInteger 就可以往里面加入 Integer 对象了这明显会造成 ClassCastException。泛型的存在用于限定类型的这么一搞泛型就失去了其作用。 这里大家可以简单理解为当泛型参数不一样时两个类就没有太大关系了。例如 ArrayListInteger 和 ListNumber 两者完全没有继承关系。 编写泛型 知道怎么使用系统的泛型之后我们现在就来看看如何编写自己的泛型类。 泛型作为对类型进行限制的一种方式我们编写泛型代码也就是对使用我们代码的人进行一种限制。在这种情况下我们是作为其他程序员的底层向上提供某种框架代码让其他程序员能够在我们设定的框架中更容易地编写代码实现功能。这有点类似于库的开发者或是框架开发者作为这种角色写好泛型代码就更显得尤为重要了。毕竟你也不想让别人说这代码写得就跟一坨屎一样吧。 编写泛型类 编写泛型类是比普通类要复杂的。这里我们就用 PairF, S 这个类作为目标一步一步编写出一个合格的泛型类。Pair 类是 Android 开发中一个简单的使用工具类用于存储一对相关联的对象。 我们的第一版 Pair 只能使用没有使用泛型 public class Pair {public final String first;public final String second; }那这肯定是不行的因为这个 Pair 只能存放 String 类型的 first 和 second那了能够存放所有类型我们就使用泛型 T public class PairT {public final T first;public final T second; }我们把 first 和 second 用 T 来修饰表示其这两个成员变量是 T 类型的。而这个 T 类型Java 是不知道的我们必须声明告诉 Java 这是一个类型因此类名从 Pair 变成了 PairT后面的 T 就是我们的泛型类型声明。 上面的代码看上去没问题但是这个 PairT 只能存放的 first 和 second 必须是相同的类型 T那不同类型的怎么办呢这时候我们再加一个泛型不就行了 public class PairF, S {public final F first;public final S second; }在加入两个泛型之后first 和 second 的类型对应不同的泛型这样就可以表示不同的类型了注意 F、S 这两个不同的泛型都需要在类上进行声明。 我们在为 PairF, S 添加个构造方法 public class PairF, S {public final F first;public final S second;public Pair(F first, S second) {this.first first;this.second second;} }这算是一个简单的泛型类那接下来我们再为它编写一个泛型方法。 编写泛型方法 此处的泛型方法是指静态方法而不是成员方法。这两种方法在使用泛型时是有一些区别的其中最重要的一点就是静态方法是不能使用类上声明的泛型类型必须得自己声明泛型类型。例如下面的代码将编译错误 public static class PairF, S {public final F first;public final S second;//编译错误F、S 类型不能在 static 方法上使用public static PairF, S create(F a, S b) {return new PairF, S(a, b);} }可以想一想为什么静态方法不能使用类上已经声明的泛型类型呢 在回答这个问题之前我们可以先想一下类上的泛型类型是在什么时候确定下来的呢是在类创建的时候我们在 new 的时候是需要提供具体类型的这个时候泛型就被具体化为某个特定类型。不同的对象可能被创建为不同的类型而静态方法只跟类相关跟具体对象无关而这些泛型又是跟具体对象相关的。所以静态对象不能使用类上声明的泛型也就变得合理了。 那要想使静态方法使用泛型那就必须这个静态方法自己声明泛型 public static F, S Pair F, S create(F a, S b) {return new PairF, S(a, b); }这个静态方法在函数名前使用 F, S 来声明了两个泛型那么后续这两个泛型就可以在这个函数中使用了。此时注意这里的 F、S 虽然与 Pair 上的 F、S 泛型看似相同实际上是没有任何关系的。所以为了避免产生误会一般都会使用不同的泛型名例如将这个方法的 F, S 变成 A, B public static class PairF, S {public final F first;public final S second;public static A, B Pair A, B create(A a, B b) {return new PairA, B(a, b);} }这样才能够清楚地将静态方法的泛型类型和实例类型的泛型类型区分开。 在使用时我们可以使用如下代码创建一个 PairF, S 实例 PairString, Integer pair Pair.create(123, 123);这里总结一下编写泛型需要注意的几点 编写泛型时需要定义泛型类型 T静态方法不能引用类上的泛型类型 T必须定义自己方法特有的泛型类型泛型可以同时定义多个例如 F, S、F、S、T 在这里我们需要注意泛型的一个限制那就是不能使用泛型类型直接创建对象。这一点也好理解T 是什么类型只有在使用时指定了泛型的具体类型才能确定。T 类型是一个抽象的类型它是无法直接 new 出来的就像你无法直接 new 一个 interface 一样。例如下面的代码是错误的 public static class PairF, S {public final F first;public final S second;public Pair(F first, S second) {this.first new F(); //错误this.second new S(); //错误} }这里使用 F 类型的默认构造设想一下假如这个类型被确定为一个没有默认构造方法的类型呢。所以使用泛型类型创建对象是不行的。 Java 的泛型实现方式类型擦除 上面的几节介绍了泛型的好处泛型的使用那这一节我们就来看看 Java 是如何实现泛型技术的。 首先泛型编程并非 Java 特有的在其他语言 C、C# 上都有类似的技术只不过名称不同而已例如 C 上叫模版。在这些技术的加持下程序员可以编写与具体类型无关的代码只需要在使用时指定具体类型从而提高代码的复用性并且在编译时进行类型检查减少运行时错误。 Java 的泛型是通过类型擦除Type Erasure来实现的。也就是说在编译时将泛型类型擦除替换为其上限类型通常为 Object并在必要时插入类型转换。这种机制在编译时处理泛型类型而在运行时移除了所有的泛型信息因此叫做类型擦除。 这也就意味着Java 的泛型是由编译器实现的在编译成 class 文件时类型信息已经被擦除了因此运行时Java 虚拟机是没有任何泛型信息的。 例如上面我们编写的 Pair 的这个类在我们看来它是这样的在源代码阶段里面是包含泛型信息的 public static class PairF, S {public final F first;public final S second;public Pair(F first, S second) {this.first first;this.second second;}public static A, B PairA, B create(A a, B b) {return new PairA, B(a, b);} }那么在虚拟机的视角它是这样的 public class Pair {private Object first;private Object last;public Pair(Object first, Object last) {this.first first;this.last last;} }从这里就能看到这个 Pair 在运行时已经没有泛型信息了所有的泛型类型都被替换为了 Object。 那么既然我们定义的泛型类型最终都变成了 Object那我们就知道了 Java 泛型的一个局限泛型类型 T 不能是基本类型。 因为像 int、float 这些基本类型不是 Object 的子类所以我们必须使用包装类 Pairfloat, int pair Pair.create(3.15, 123); //编译错误 PairFloat, Integer pair Pair.create(3.15F, 123); //编译通过尽管 Java 的泛型在编译时通过类型擦除机制移除了泛型类型信息但 Java 编译器会在 class 文件中保留一些泛型信息以便工具和开发人员能够利用这些信息进行反射和调试。所以如果大家把这个类编译为 class 文件之后再查看它的反编译的内容会发现它是有一些泛型信息的。但这并不意味着 JVM 在运行时会携带这些类型信息既然是类型擦除也就是说泛型类型参数被擦除并替换为其边界类型如果没有指定边界则默认为 Object。 这里又引入了边界类型这个概念在下一篇文章中我们就来详细聊聊这个边界类型这也是泛型中比较重要和难的点。
http://www.hkea.cn/news/14410730/

相关文章:

  • 站点提交网站建设企业站模板
  • 免费域名申请网站怎样用编程语言做网站
  • 个人主页网站申请做网站要服务器和什么
  • 东莞网站设计师湖北seo排名诊断
  • 温州旅游 网站建设网站建设重点是什么
  • 门户网站怎么做wordpress修改背景
  • 深圳网站建设方维网络网站建设实施计划
  • 暴利产品竞价单页网站seo优化方式包括
  • 给女朋友做网站 知乎医院网站建设台账
  • 网站后台无法更新缓存内蒙古建设部网站官网
  • 专业网站设计 网络服务网站的修改
  • 深圳宝安高端网站建设公司wordpress子站点解析
  • 专业的建设企业网站公司wordpress首页图片幻灯片播放
  • 如何做网站编辑 沒技术上海搜索引擎优化公司排名
  • 网站运营情况怎么写龙岩天宫山旅游攻略
  • 建筑公司网站应该则么做北京企业网站开发公司哪家好
  • 网站seo的推广计划用表格做网站教程
  • 邯郸网站建设xy0310网站建设只有20%的利润
  • 设计外包网站中小企业网站建设中服务器的解决方案是
  • jsp网站怎么做邮箱验证码西安百度seo
  • 企业网站建设联系网站建设公司 待遇
  • 免费设计自己名字头像宁波正规优化seo软件
  • 天津网站设计网站制作mx主题wordpress
  • 膳食管理东莞网站建设莆田网站建设团队
  • 阿里 域名解析 网站建设课程网站建设毕业设计
  • 南京网站建设 雷网站搭建的
  • 网站建设服务费的会计处理公司网站开发计划书
  • 深圳企业公司网站建设平台wordpress自动锚文本
  • 网站后台密码怎么改休闲吧网站建设
  • 工商注册在哪个网站长沙网站设计我选刻