前言:
https://www.cnblogs.com/LoveBB/p/17277662.html
JDK 1.5开始引入Java泛型(generics)这个特性,该特性提供了编译时类型安全检测机制,允许程序员在编译时检测到非法的类型。停,业余的客套话就不多说了,这些术语,讲了N遍,不管你看不看得懂,我的目的就是就要把你教懂,所以,这里不是重点。
泛型有四个作用:类型安全、自动转换、性能提升、可复用性。即在编译的时候检查类型安全,将所有的强制转换都自动和隐式进行,同时提高代码的可复用性。实在不想说,但是不说又不行,生怕你们把路走偏了。
public class Student {
}
public class Teacher {
}
public class Room {
}
有些人心里忍不住要喷了,这谁不会呀。嘿嘿,别着急,这想说的就是我们修炼的名门正派功法,这是很标准的"正派"写法。接下来,我将使用魔教功法进行魔改。
public class 类名 <泛型类型1,...> {
// todo
}
简简单单
public class Student<T> {
}
我好像在骂人,但是你没有证据吧
public class Student<S,B> {
}
这里注意,范型里面的 S, B, Q 都是自定义的,一般用大写字母表示,个数不限
public class Student<S, B, Q> {
}
嘿嘿,个数不限,那就来个不限的吧
public class Student<S, B, Q, V, N, F, D, A, U, I, O, P, L, H, J, K, G> {
}
有人说,字母就26个啊,你写重复的话,那不是一样了嘛。对,你是对的,但是魔教功法就在于,他不讲道理,谁说一定要使用大写字母了,下面来个逼死强迫症写法,什么叫无限火力,放飞自我。
public class Student<Sq, VIP, diss, QR, LKl, WOrd, Hao, Da, VPP, Ji, Ni, Tai, Mei, N, WoCao, D, CPDD, U, I, Love, Dog, OPHJKG, JiuK, HangZhou, WO, LAi, CoffEr, VCS> {
}
怎么样,好好的一个类,经过魔教功法的改造,是不是看起来很不一样了。
虽然我们可以乱写,但是魔教功法还是有一套自己的体系,一般关于大写字母的定义如下
T:任意类型 type
E:集合中元素的类型 element
K:key-value形式 key
V: key-value形式 value
N: Number(数值类型)
?: 表示不确定的java类型
// 改造前
public class Student {
}
// 改造后
public class Student<T> {
}
// 正经写法
Student student = new Student();
// 范型写法
Student<T> student = new Student<>();
// 案例1
Student<String> student = new Student<>();
// 案例2
Student<Integer> student = new Student<>();
// 案例3
Student<Teacher> student = new Student<>();
// 案例4:前面都没意思,来试试套娃吧,哈哈,走火入魔了没有,魔功就是魔功,这里要自己动手,才清晰明了
Student<Student<Student<Student<Student<String, Student<String, Long>>, Boolean>, Integer>, String>, Student<String, Integer>> student = new Student<>();
// 案例5:那个最长的,我实在懒得写了,后面全部用String代替了,这一套写下来,能不能唬住人。
Student<
String,
BigDecimal,
Integer,
Boolean,
Long,
Double,
Room,
Teacher,
String,
String,
String,
String,
String,
String,
String,
String,
String
> student = new Student<>();
咱就是说,用了魔教功法之后,我们 new 出来的对象,想传什么就传什么。有多少个范型参数,就传多少个对象进去。总之就一句话,很强,运用好了,绝对是秒天秒地秒空气。crud 之内,已然无敌。
看过范型类了,那接下来就是接口。有一说一,范型接口的使用率比范型类高出很多很多
public interface Student {
// todo
}
public interface 接口名<T> {
// todo
}
public interface Student<T> {
// todo
}
public interface Student<S, B> {
// todo
}
停,就到这里吧,再写下去就不礼貌了,容易走火入魔。参数是和类一样的,可以N个,英文字母不限大小。
// 改造前
public interface Student {
// todo
}
// 改造后
public interface Student<T> {
// todo
}
众所周知,接口只能用实现接口的方式来实例化,java8之后还能用函数式编程,这里就不展开来讲了
// 正经实现
public class GoodStudent implements Student{
}
// 范型实现
public class GoodStudent<T> implements Student<T>{
}
// 这里不用 T 可不可以呢,答案是可以的,只要子类和父类的范型一样就行
public class GoodStudent<B> implements Student<B>{
}
// 实战1
public class GoodStudent<String> implements Student<String>{
}
// 实战2
public class GoodStudent<Integer> implements Student<Integer>{
}
// 实战N,别忘记了我们还能套娃,还能无限火力N,这里就不演示了

那说了那么多,这个范型有什么用呢,答案是:接口、类声明中定义的类型形参则可以在整个接口、类中使用。
可以作为参数类型,入参,返回值使用
public class GoodStudent<T> implements Student<T>{
// 范型作为参数类型
private T personality;
// 范型接口1,作为入参
public void evaluation(T t){
}
// 范型接口2,作为入参和返回值
public T evaluation2(T t){
return t;
}
}
// 实例化后很简单的,一看就懂,这就是我们正常的写法
public class GoodStudent<String> implements Student<String>{
// 范型参数
private String personality;
public void evaluation(String t){
}
public String evaluation2(String t){
return t;
}
}
// 案例2
public class GoodStudent<Integer> implements Student<Integer>{
// 范型参数
private Integer personality;
public void evaluation(Integer t){
}
public Integer evaluation2(Integer t){
return t;
}
}
public static void main(String[] args) {
// String 类型
GoodStudent<String> goodStudent = new GoodStudent<>();
String personality = "";
goodStudent.evaluation(personality);
String result = goodStudent.evaluation2(personality);
// Integer 类型
GoodStudent<Integer> goodStudent = new GoodStudent<>();
Integer personality = "";
goodStudent.evaluation(personality);
Integer result = goodStudent.evaluation2(personality);
// 套娃类型,我就套一层,不然容易走火入魔
GoodStudent<GoodStudent<String>> goodStudent = new GoodStudent<>();
GoodStudent<String> personality = new GoodStudent<>();
// 内层
String resultString = personality.evaluation2("");
goodStudent.evaluation(personality);
// 外层
GoodStudent<String> result = goodStudent.evaluation2(personality);
}
// 无返回值,无入参
public void test(){
}
// 无返回值,有入参
public void test(String s){
}
// 有返回值,无入参
public String test(){
return "";
}
// 有返回值,有入参
public String test(String s){
return s;
}
// 范型方法就是加上一个范型声明
public <泛型类型> 返回类型 方法名(泛型类型 变量名) {
// todo
}
// 无返回值,无入参(无意义)
public <T> void test(){
}
// 无返回值,有入参(不常用)
public <T> void test(T s){
}
// 有返回值,无入参(不太常用)
public <T> T test(){
retrn null;
}
// 有返回值,有入参(经常用)
public <T> T test(T s){
return s;
}
public class GoodStudent implements Student {
// 无返回值,无入参
public void test() {
}
// 无返回值,有入参
public void test2(String s) {
}
// 有返回值,无入参
public String test3() {
return "";
}
// 有返回值,有入参
public String test4(String s) {
return s;
}
}
public static void main(String[] args) {
GoodStudent goodStudent = new GoodStudent();
goodStudent.test();
String s = "";
goodStudent.test2(s);
String s1 = goodStudent.test3();
String s2 = goodStudent.test4(s);
}
public class GoodStudent implements Student {
// 无返回值,无入参(无意义)
public <T> void test(){
}
// 无返回值,有入参(不常用)
public <T> void test2(T s){
}
// 有返回值,无入参(不太常用)
public <T> T test3(){
return null;
}
// 有返回值,有入参(经常用)
public <T> T test4(T s){
return s;
}
}
public static void main(String[] args) {
// String 范型
GoodStudent goodStudent = new GoodStudent();
goodStudent.test();
String s = "";
goodStudent.test2(s);
String s1 = goodStudent.test3();
String s2 = goodStudent.test4(s);
// Integer 范型
GoodStudent goodStudent = new GoodStudent();
goodStudent.test();
Integer s = "";
goodStudent.test2(s);
Integer s1 = goodStudent.test3();
Integer s2 = goodStudent.test4(s);
// Student<String> 范型
GoodStudent goodStudent = new GoodStudent<>();
goodStudent.test();
Student<String> s = new GoodStudent<>();
goodStudent.test2(s);
Student<String> s1 = goodStudent.test3();
Student<String> s2 = goodStudent.test4(s);
}
范型方法是传什么参数,就是什么返回值
你以为这就完了?下面才是绝杀。
Java泛型的通配符是用于解决泛型之间引用传递问题的特殊语法, 主要有以下三类:
无边界更多是服务于上界和下界的
// 表示类型参数可以是任何类型
public class B<?> {
}
// 上界:表示类型参数必须是A或者是A的子类
public class B<T extends A> {
}
// 下界:表示类型参数必须是A或者是A的超类型
public class B<T supers A> {
}
public class GoodStudent implements Student{
// String参数
private String personality;
// String 作为入参
public void evaluation(String t){
}
// String作为入参和返回值
public String evaluation2(String t){
return t;
}
}
public class GoodStudent<T> implements Student<T>{
// 范型参数
private T personality;
// 范型接口1,作为入参
public void evaluation(T t){
}
// 范型接口2,作为入参和返回值
public T evaluation2(T t){
return t;
}
}
public class GoodStudent<T extends String> implements Student<T> {
// 范型参数
private T personality;
// 范型接口1,作为入参
public void evaluation(T t){
}
// 范型接口2,作为入参和返回值
public T evaluation2(T t){
return t;
}
}
到这里,我已经走火入魔了,后续的后面在写了,从这里我们也能看出,一个“正派”的类,经过”魔教“功法范型的改造之后,已经具备一定的复杂性了。这就是 魔功-范型 带来的威力。
// 改造前
public class GoodStudent implements Student{
// String参数
private String personality;
// String 作为入参
public void evaluation(String t){
}
// String作为入参和返回值
public String evaluation2(String t){
return t;
}
}
// 改造后
public class GoodStudent<T extends String> implements Student<T> {
// 范型参数
private T personality;
// 范型接口1,作为入参
public void evaluation(T t){
}
// 范型接口2,作为入参和返回值
public T evaluation2(T t){
return t;
}
}
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur
在Java中,可以像这样从一个字符串创建一个IO流:Readerr=newStringReader("mytext");我希望能够在Ruby中做同样的事情,这样我就可以获取一个字符串并将其视为一个IO流。 最佳答案 r=StringIO.new("mytext")和here'sthedocumentation. 关于java-Java的StringReader的Ruby等价物是什么?,我们在StackOverflow上找到一个类似的问题: https://st