网站地图提交入口,怎么在网站做自己的产品广告,湖州 外贸网站建设,成都有什么好玩的景点推荐泛型
Java 泛型#xff08;Generics#xff09; 是 JDK 5 中引入的一个新特性。使用泛型参数#xff0c;可以增强代码的可读性以及稳定性。
编译器可以对泛型参数进行检测#xff0c;并且通过泛型参数可以指定传入的对象类型
ArrayListPerson persons new Arra…泛型
Java 泛型Generics 是 JDK 5 中引入的一个新特性。使用泛型参数可以增强代码的可读性以及稳定性。
编译器可以对泛型参数进行检测并且通过泛型参数可以指定传入的对象类型
ArrayListPerson persons new ArrayListPerson()
这行代码就指明了该 ArrayList 对象只能传入 Person 对象如果传入其他类型的对象就会报错
并且原生 List 返回类型是 Object 需要手动转换类型才能使用使用泛型后编译器自动转换
泛型的使用方式有哪几种
泛型一般有三种使用方式:泛型类、泛型接口、泛型方法
1.泛型类
//此处T可以随便写为任意标识常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时必须指定T的具体类型
public class GenericT{
private T key;
public Generic(T key) {this.key key;}
public T getKey(){return key;}
}
那该怎么实例化泛型类呢
GenericInteger genericInteger new GenericInteger(123456);
2.泛型接口
public interface GeneratorT {public T method();
}
无指定类型实现泛型接口
class GeneratorImplT implements GeneratorT{Overridepublic T method() {return null;}
}
指定类型实现泛型接口
class GeneratorImpl implements GeneratorString {Overridepublic String method() {return hello;}
}
3.泛型方法 public static E void printArray( E[] inputArray ){for ( E element : inputArray ){System.out.printf( %s , element );}System.out.println();}
怎么使用泛型方法呢
// 创建不同类型数组Integer, Double 和 Character
Integer[] intArray { 1, 2, 3 };
String[] stringArray { Hello, World };
printArray( intArray );
printArray( stringArray ); 注意: public static E void printArray( E[] inputArray ) 一般被称为静态泛型方法;在 java 中泛型只是一个占位符必须在传递类型后才能使用。类在实例化时才能真正的传递类型参数由于静态方法的加载先于类的实例化也就是说类中的泛型还没有传递真正的类型参数静态的方法的加载就已经完成了所以静态泛型方法是没有办法使用类上声明的泛型的。只能使用自己声明的 E 将泛型运用到实际项目当中又有哪里能用到泛型呢 自定义接口通用返回结果 CommonResultT 通过参数 T 可根据具体的返回类型动态指定结果的数据类型 定义 Excel 处理类 ExcelUtilT 用于动态指定 Excel 导出的数据类型 构建集合工具类参考 Collections 中的 sort, binarySearch 方法。 .........................................................
反射
什么是反射
如果说大家研究过框架的底层原理或者咱们自己写过框架的话一定对反射这个概念不陌生。
反射之所以被称为框架的灵魂主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。
通过反射你可以获取任意一个类的所有属性和方法你还可以调用这些方法和属性非常方便、灵活
像咱们平时大部分时候都是在写业务代码很少会接触到直接使用反射机制的场景。
但是这并不代表反射没有用。相反正是因为反射你才能这么轻松地使用各种框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制这些框架中也大量使用了动态代理而动态代理的实现也依赖反射,在Java的注解当中也运用到了反射的机制
为啥在使用Spring框架时用一个Component就能直接声明一个类为Bean为啥使用Value就能轻松读取配置文件中的配置项这些都是得益于反射的机制因为可以基于反射分析类然后获取到类/属性/方法/方法的参数上的注解。你获取到注解之后就可以做进一步的处理
谈谈反射机制的优缺点
那么在反射带来了便利的同时其实也有一些负面影响
优点可以让咱们的代码更加灵活、为各种框架提供开箱即用的功能提供了便利
缺点让我们在运行时有了分析操作类的能力这同样也增加了安全问题。比如可以无视泛型参数的安全检查泛型参数的安全检查发生在编译时、会破坏封装性。另外反射的性能也要稍差点但其实对于框架来说实际是影响不大的
注解
什么是注解
Annotation 注解 是 Java5 开始引入的新特性可以看作是一种特殊的注释主要用于修饰类、方法或者变量提供某些信息供程序在编译或者运行时使用。
注解本质其实就是一个继承了Annotation 的特殊接口
Target(ElementType.METHOD)
Retention(RetentionPolicy.SOURCE)
public interface Override {
}
public interface Override extends Annotation{
}
JDK 提供了很多内置的注解比如 Override、Deprecated同时我们还可以自定义注解
注解只有被解析了之后才会生效有两种解析方法 编译期直接扫描编译器在编译 Java 代码的时候扫描对应的注解并处理比如某个方法使用Override 注解编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。 运行期通过反射处理像框架中自带的注解(比如 Spring 框架的 Value、Component)都是通过反射来进行处理的。
SPI
什么是SPI
SPI 即 Service Provider Interface 字面意思就是“服务提供者的接口”我的理解是专门提供给服务提供者或者扩展框架功能的开发者去使用的一个接口。
SPI 将服务接口和具体的服务实现分离开来将服务调用方和服务实现者解耦能够提升程序的扩展性、可维护性。修改或者替换服务实现并不需要修改调用方。
很多框架都使用了 Java 的 SPI 机制比如Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等
SPI 和 API 有什么区别
说到 SPI 就不得不说一下 APIApplication Programming Interface 了从广义上来说它们都属于接口而且很容易混淆
一般模块之间都是通过接口进行通讯因此我们在服务调用方和服务实现方也称服务提供者之间引入一个“接口” 当实现方提供了接口和实现我们可以通过调用实现方的接口从而拥有实现方给我们提供的能力这就是 API。这种情况下接口和实现都是放在实现方的包中。调用方通过接口调用实现方的功能而不需要关心具体的实现细节。 当接口存在于调用方这边时这就是 SPI 。由接口调用方确定接口规则然后由不同的厂商根据这个规则对这个接口进行实现从而提供服务。
打个比方英伟达公司生产了一块显卡4090马上进入量产阶段而市面上有很多种电脑主机的主板制造业公司这时只需要英伟达官方定义好显卡接口的标准规则定义好了接口标准那么这些合作公司服务提供者就直接按照标准实现主板的开发就好了虽然他们生产的主板都不一样但是最终的结果都是为了适配英伟达公司生产的这块显卡的接口。提供不同方案的实现但是给出来的结果是一样的
SLF4J Simple Logging Facade for Java是 Java 的一个日志门面接口其具体实现有几种比如Logback、Log4j、Log4j2 等等而且还可以切换在切换日志具体实现的时候我们是不需要更改项目代码的只需要在 Maven 依赖里面修改一些 pom 依赖就好了其实这就是依赖 SPI 机制实现的 SPI 机制在很多框架中都有应用Spring 框架的基本原理也是类似的方式。还有 Dubbo 框架提供同样的 SPI 扩展机制只不过 Dubbo 和 spring 框架中的 SPI 机制具体实现方式跟我讲的这个有些细微的区别不过整体的原理都是一致的
通过 SPI 机制能够大大地提高接口设计的灵活性但是 SPI 机制也存在一些缺点比如 遍历加载所有的实现类这样效率还是相对较低的 当多个 ServiceLoader 同时 load 时会有并发问题。