仿制药名言_仿制药的美丽与陌生
仿制药名言
最近,我正在为Oracle认证专家Java SE 7程序员考试做准备,而我恰巧在Java泛型领域遇到了一些看起来很奇怪的构造。 但是,我也看到了一些巧妙而优雅的代码。 我发现这些示例值得分享,这不仅是因为它们可以使您的设计选择更加容易,并且使代码更加健壮和可重用,而且还因为其中的某些示例在您不习惯泛型时非常棘手。 我决定将这篇文章分为四个章节,这些章节几乎反映了我在学习和工作经历中对仿制药的经验。
您了解泛型吗?
当我们四处看看时,可以发现泛型在Java Universe的许多不同框架中都大量使用。 它们从Web应用程序框架到Java本身的集合。 由于这个话题已经在我之前被很多人解释过了,所以我将只列出我认为有价值的资源,然后转到有时根本没有提及或解释得不好的东西(通常在网上发布的注释或文章中) 。 因此,如果您不了解核心泛型概念,则可以查看以下一些材料:
- Katherine Sierra和Bert Bates的SCJP Sun认证Java 6考试程序员
- 对我而言,本书的主要目的是为参加Oracle提供的OCP考试做好准备。
- 课程: Oracle的泛型(已更新)
- 资源由Oracle本身提供。
- Maurice Naftalin和Philip Wadler的Java泛型和集合
- O'Reilly Media制作的另一本很棒的Java书籍。
泛型不允许做什么?
假设您了解泛型,并希望了解更多信息,那么请转到无法完成的工作。 令人惊讶的是,有很多东西无法与泛型一起使用。 在使用泛型时,我选择了以下六个避免陷阱的示例。
类型为<T>
静态字段
许多没有经验的程序员常犯的一个常见错误是试图声明静态成员。 在下面的示例中可以看到,任何尝试都会导致编译器错误,如下所示: Cannot make a static reference to the non-static type T
。
public class StaticMember<T> {// causes compiler errorstatic T member;
}
类型为<T>
实例
另一个错误是尝试通过在泛型类型上调用new来实例化任何类型。 这样,编译器将导致错误提示: Cannot instantiate the type T
public class GenericInstance<T> {public GenericInstance() {// causes compiler errornew T();}
}
与原始类型不兼容
使用泛型时最大的限制之一似乎是它们与原始类型不兼容。 的确,您不能在声明中直接使用基元,但是,可以用适当的包装器类型替换基元,然后就可以了。 整个情况在以下示例中呈现:
public class Primitives<T> {public final List<T> list = new ArrayList<>();public static void main(String[] args) {final int i = 1;// causes compiler error// final Primitives<int> prim = new Primitives<>();final Primitives<Integer> prim = new Primitives<>();prim.list.add(i);}
}
在编译期间, Primitives
类的第一个实例化将失败,并出现与以下错误类似的错误: Syntax error on token "int", Dimensions expected after this token
。 使用包装器类型和少量自动装箱魔术可绕过此限制。
<T>
类型的数组
使用泛型的另一个明显限制是无法实例化泛型类型的数组。 考虑到数组对象的基本特征,原因很明显–它们在运行时保留其类型信息。 如果违反了它们的运行时类型完整性,则运行时异常ArrayStoreException可以挽救这一天。
public class GenericArray<T> {// this one is finepublic T[] notYetInstantiatedArray;// causes compiler errorpublic T[] array = new T[5];
}
但是,如果尝试直接实例化一个通用数组,则将出现如下编译错误: Cannot create a generic array of T
。
通用异常类
有时,程序员可能需要传递泛型类型的实例以及引发异常。 这在Java中是不可能的。 下面的示例描述了这种努力。
// causes compiler error
public class GenericException<T> extends Exception {}
当您尝试创建这样的异常时,您将得到如下消息: The generic class GenericException<T> may not subclass java.lang.Throwable
。
关键字super
和extends
替代含义
值得一提的最后一个限制,特别是对于新手来说,是泛型时关键字super
和extends
的替代含义。 为了生成利用泛型的精心设计的代码,了解这一点非常有用。
<? extends T>
- 含义:通配符是指扩展类型T和类型T本身的任何类型。
<? super T>
- 含义:通配符是指T的任何超类型以及T本身。
一点点的美
关于Java我最喜欢的事情之一是它的强类型。 众所周知,泛型是在Java 5中引入的,它们被用来使我们更容易使用集合(它们不仅在集合中被用于更多领域,但这是设计阶段泛型的核心论点之一) 。 即使泛型仅提供编译时保护,并且不输入字节码,但它们提供了相当有效的方式来确保类型安全。 以下示例显示了泛型的一些不错的功能或用例。
泛型适用于类和接口
这可能一点都不令人惊讶,但是是的-接口和泛型是兼容的构造。 尽管将泛型与接口结合使用非常普遍,但我发现这一事实实际上是非常酷的功能。 这使程序员可以在考虑类型安全和代码重用的情况下创建甚至更高效的代码。 例如,考虑以下来自包java.lang
接口Comparable
示例:
public interface Comparable<T> {public int compareTo(T o);
}
泛型的简单介绍使得有可能从compareTo
方法中省略check实例,从而使代码更具凝聚力并提高了可读性。 通常,泛型有助于使代码更易于阅读和理解,并有助于引入类型顺序。
泛型允许优雅使用范围
关于限制通配符,有一个很好的例子说明了在库类Collections
可以实现的目标。 此类声明方法copy
,该方法在以下示例中定义,并使用有界通配符来确保列表的复制操作的类型安全。
public static <T> void copy(List<? super T> dest, List<? extends T> src) { ... }
让我们仔细看看。 方法copy
被声明为返回void的静态泛型方法。 它接受两个参数-目标和源(并且两者都是有界的)。 目标必须存储仅属于T
或T
类型本身的超类型的类型。 另一方面,源必定仅由T
类型的扩展类型或T
类型本身构成。 这两个约束保证了集合和复制操作都保持类型安全。 我们不需要使用数组,因为它们通过抛出上述ArrayStoreException
异常防止了任何类型安全冲突。
泛型支持多边界
不难想象为什么人们会只使用一种简单的边界条件而不是使用更多的条件。 实际上,这样做很容易。 考虑以下示例:我需要创建一个接受参数的方法,该参数既是Comparable
也是数字List
。 开发人员将被迫创建不必要的接口ComparableList,以便在通用时间内履行上述合同。
public class BoundsTest {interface ComparableList extends List, Comparable {}class MyList implements ComparableList { ... }public static void doStuff(final ComparableList comparableList) {}public static void main(final String[] args) {BoundsTest.doStuff(new BoundsTest().new MyList());}
}
在执行此任务之后,我们可以忽略这些限制。 使用泛型可以使我们创建满足所需合同的具体类,但使doStuff
方法尽可能开放。 我发现的唯一缺点是语法相当冗长。 但是,由于它仍然保持很好的可读性和易于理解性,因此我可以忽略此缺陷。
public class BoundsTest {class MyList<T> implements List<T>, Comparable<T> { ... }public static <T, U extends List<T> & Comparable<T>> void doStuff(final U comparableList) {}public static void main(final String[] args) {BoundsTest.doStuff(new BoundsTest().new MyList<String>());}
}
有点奇怪
我决定为这篇文章的最后一章专门介绍到目前为止我遇到的两种最奇怪的构造或行为。 您极有可能永远不会遇到这样的代码,但是我发现提到它很有趣。 因此,事不宜迟,让我们见识这些奇怪的东西。
尴尬的代码
与任何其他语言构造一样,您可能最终会遇到一些看起来很奇怪的代码。 我想知道最奇怪的代码是什么样的,以及它是否甚至可以通过编译。 我能想到的最好的是下面的代码。 您可以猜测该代码是否可以编译?
public class AwkwardCode<T> {public static <T> T T(T T) {return T;}
}
即使这是一个非常糟糕的编码示例,也可以成功编译,并且应用程序可以正常运行。 第一行声明泛型类AwkwardCode
,第二行声明泛型方法T
方法T
是返回T
实例的通用方法。 它采用T
类型的参数,不幸的是称为T
该参数也会在方法主体中返回。
通用方法调用
最后一个示例显示了与泛型结合使用时类型推断的工作原理。 当我看到一段代码不包含方法调用的通用签名却声称要通过编译时,我偶然发现了这个问题。 当某人对泛型只有很少的经验时,这样的代码可能一见钟情。 您能否解释以下代码的行为?
public class GenericMethodInvocation {public static void main(final String[] args) {// 1. returns trueSystem.out.println(Compare.<String> genericCompare("1", "1"));// 2. compilation errorSystem.out.println(Compare.<String> genericCompare("1", new Long(1)));// 3. returns falseSystem.out.println(Compare.genericCompare("1", new Long(1)));}
}class Compare {public static <T> boolean genericCompare(final T object1, final T object2) {System.out.println("Inside generic");return object1.equals(object2);}
}
好吧,让我们分解一下。 第一次调用genericCompare
非常简单。 我表示参数类型将是什么类型的方法,并提供该类型的两个对象-此处没有奥秘。 由于Long
不是String
对genericCompare
第二次调用无法编译。 最后,对genericCompare
第三次调用返回false
。 这很奇怪,因为该方法被声明为接受相同类型的两个参数,但是最好将其传递给String
文字和Long
对象。 这是由编译期间执行的类型擦除过程引起的。 由于方法调用未使用泛型的<String>
语法,因此编译器无法告诉您要传递两种不同的类型。 始终记住,最接近的共享继承类型用于查找匹配的方法声明。 意思是,当genericCompare
接受object1
和object2
,它们被genericCompare
转换为Object
,但由于运行时多态性而被比较为String
和Long
实例–因此该方法返回false
。 现在让我们修改一下代码。
public class GenericMethodInvocation {public static void main(final String[] args) {// 1. returns trueSystem.out.println(Compare.<String> genericCompare("1", "1"));// 2. compilation errorSystem.out.println(Compare.<String> genericCompare("1", new Long(1)));// 3. returns falseSystem.out.println(Compare.genericCompare("1", new Long(1)));// compilation errorCompare.<? extends Number> randomMethod();// runs fineCompare.<Number> randomMethod();}
}class Compare {public static <T> boolean genericCompare(final T object1, final T object2) {System.out.println("Inside generic");return object1.equals(object2);}public static boolean genericCompare(final String object1, final Long object2) {System.out.println("Inside non-generic");return object1.equals(object2);}public static void randomMethod() {}
}
此新代码示例通过添加genericCompare
方法的非泛型版本并定义一个不执行任何操作并从GenericMethodInvocation
类的main
方法调用两次的新randomMethod
来修改Compare
类。 由于我提供了与给定调用匹配的新方法,因此该代码使对genericCompare
的第二次调用genericCompare
可能。 但这引发了一个关于另一个奇怪行为的问题–第二个呼叫是否通用? 事实证明–不,不是。 但是,仍然可以使用泛型的<String>
语法。 为了更清楚地展示此功能,我使用此通用语法创建了对randomMethod
新调用。 再次由于类型擦除过程而实现了这一点-擦除了这种通用语法。
但是,当有界通配符出现在舞台上时,这种情况会改变。 编译器以编译器错误的形式向我们发送清晰的消息,说: Wildcard is not allowed at this location
,这使得无法编译代码。 要编译和运行代码,必须注释掉第12行。以这种方式修改代码后,它将产生以下输出:
Inside generic
true
Inside non-generic
false
Inside non-generic
false
翻译自: https://www.javacodegeeks.com/2014/06/beauty-and-strangeness-of-generics.html
仿制药名言
仿制药名言_仿制药的美丽与陌生相关推荐
- 通过一致性评价的仿制药和原研药“一样”吗
很多人会问:仿制药经过"一致性评价"后,是不是就和原研药一样了呢?那首先得了解一致性评价 的背景和要求: 国内药物一致性评价自2012年开始试点, 2016年国务院发文,仿制药一致 ...
- python的十句名言_十句名人名言
俗话说得好:会干的不如会说的.你想仅仅凭着熟练的技能和勤恳的工作,就在职场游刃有余.出人头地,未免有些天真了.虽然能力加勤奋很重要,但会说话,却能让你工作起来更轻松,并且可能帮助你加薪.升职.1.应答 ...
- typescript获取数据库数据_肿瘤药敏多组学数据库(GDSC)的数据介绍和获取
在第一期的GDSC数据总览中,我们根据数据库的模块进行总体的介绍.今天我们再深入了解GDSC所包含的数据及其获取的方法,也就是GDSC的数据下载模块. GDSC数据下载的模块,分为4个模块,分别是AN ...
- 印章仿制工具_仿制图章工具原来还能这么用!
原标题:仿制图章工具原来还能这么用! 本文作者:Miller姚明来 仿制图章(克隆)工具,是ps中最基础的工具,这是连刚刚入门的新手都熟练掌握的,往往只被我们用来修补和去除画面中的杂物,让图片更简洁. ...
- mysql万能匹配_万能药模式匹配
mysql万能匹配 In this story, we will see together the different aspects of Elixir Pattern Matching: tupl ...
- 公需科目必须学吗_执业药师公需科目是必须学的吗?
摘要:是的,如果你有执业药师继续教育公需科目全年都是要求完成30个学分的,所以也就是说必须要学习.一.是否取消证书 但是如果我们在有这个资格证的时候不学习的话,也并不会取消你的证书. 学习的内容其实相 ...
- 利用ccle数据库构造分类器区分耐药与不耐药样本
文章目录 下载数据 ccle数据下载 读入数据(以CCLE的数据为例) 提取自己想要的数据 制作标签 进行T检验 将数据保存到本地 将数据处理成weka输入的文件格式 训练集 测试集 将CSV文件转化 ...
- 鸡的开口药如何选择 什么药防治鸡开口病最快
"开口药"这些年一直在养鸡中使用,已经形成了一个固定的观念."开口药"从字面意思就可以看出来,鸡雏开始喝第一口水,就需要添加的药物.达龙禽初乳,可以防止肠道疾病 ...
- php仿制网站,网站仿制合法吗,仿制别人网站注意事项
大家好,今天和大家说一下仿制网站时本地环境的搭建和phpcms的一些常用的后台代码,帮助新手使用. 还是以PHPCMS为例,首先在使用phpcms是,因为是后台的运行环境所以在本地安装的化需要运行环境 ...
最新文章
- 44岁的微软如何刷新未来?
- 减少科研文章写作错误的一点小技巧
- python知乎-知乎看了很多推荐,最终选了这本Python入门
- windows7 下vmware workstation 12安装Ubuntu16.04虚拟机及安装和共享文件夹
- 异步任务---SpringBoot
- freemarker -基本概念
- wpf datepicker 选择时分秒_[Angular 组件库 NG-ZORRO 基础入门] - DatePicker
- FPGA状态机一段式
- 一路走来一路歌—我和团队有个约会
- java游戏繁体字名字_游戏繁体字名字
- groupwise_SSL证书安装指南 - Groupwise 6 Netware Email Server
- 【白帽子学习笔记 22】网络扫描与网络侦查
- MongoDB-day1:MongoDB安装使用、python操作、虚拟环境、windows下pip豆瓣源配置
- 啦啦啦啦啦 报道 报道
- Python silk 库 支持微信语音
- 在浏览器中打开shell,连接linux
- macOS Monterey推出原生密码管理器,支持手动输入网址及账户
- Java二维码图片处理
- android RemoteViews解析
- 互联网盈利模式77种创新
热门文章
- POJ2446-Chessboard【最大匹配,二分图,奇偶建图】
- Educational Codeforces Round 95 (Rated for Div. 2)
- 【决策单调性】玩具装箱(金牌导航 决策单调性优化DP-1)
- 【图论】【高精】产生数(ssl 1021/ luogu 1037)
- Full_of_Boys训练6总结
- SpringCloud Greenwich(一)注册中心之nacos、Zuul和 gateway网关配置
- Sentinel(十)之系统自适应限流
- Java IO: 异常处理
- Oracle入门(十二D)之表删除与删除表数据
- SpringCloud注册中心高可用搭建