反射基础知识:
Java.lang.Class是所有类对象的定义类,同时是所有反射的入口.
Java的安全框架:Java.Security
Java.security.Permission
反射会打破OOP对象/类的封装.Java中所有类型不一定是对象,然而每种类型都是类对象(java.lang.class)
java类型:
对象类型(java.lang.Object子类) -> java.lang.Object.class
数组类型([]) -> xxx[].class
原生类型(int等) -> int.class
特殊类型(Void 仅在方法返回类型中) -> Void.class
反射性能:(性能优化)!!! AccessibleObject是Field,Method,Construct的父类,默认情况下,任何AccessObject对象都会做访问性检查,因此关闭此检查可以提升性能.setAccessible(false);
反射核心组件
类对象
- 类(Classes):java.lang.Object.class
- 接口(Interfaces):java.lang.CharSequence.class
- 枚举(Enums):java.util.concurrent.TimeUnit.class: 枚举它是特殊的类 enum xxx = final class xxx extends java.lang.Enum
字段常量(Constants)
内建行为(Build-in Behaviors)
Values()方法 -> 编译器帮助我们生成的方法
合成的父类(java.lang.Enum)
枚举的CompareTo()方法
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
只是比较类是否相同,以及字段常量的位置是否相同.不会比较内容是否相同.
- 注解(Annotation):java.lang.Override.class -> 特殊的接口 @interface TestAnnotation = public interface TestAnnotation extends java.lang.Annotation
属性方法(Attributes)
内建行为(Build-in Behaviors)
合成的接口(java.lang.annotation.Annotation)
@Documented
@Target(CONSTRUCTOR)
@Retention(RUNTIME)
public @interface ConstructorProperties {
/**
<p>The getter names.</p>
@return the getter names corresponding to the parameters in the
annotated constructor.
*/
String[] value(); // -> 属性方法
}
- 原生类型(primitives):int.class
public static void main(String[] args) {
//具体类对象
System.out.println(!Modifier.isAbstract(Object.class.getModifiers()));
//抽象类对象
System.out.println(Modifier.isAbstract(AbstractList.class.getModifiers()));
//接口类对象
System.out.println(Serializable.class.isInterface());
//枚举类对象
System.out.println(FileVisitOption.class.isEnum());
//注解类对象
System.out.println(Nullable.class.isAnnotation());
//数组类对象
System.out.println(int[].class.isArray());
//原生类对象
System.out.println(int.class.isPrimitive());
}
泛型
- 泛型信息(Generics Info):泛型参数(Parameters),泛型父类(Super Classes),泛型接口(Interfaces)
public static void main(String[] args) {
List<Integer> values = Arrays.asList(1,2,3);
System.out.println(values.getClass().toGenericString());
}
private static class java.util.Arrays$ArrayList<E>
泛型信息(Generics info)
:java.lang.Class#getGenericInfo();
泛型参数(Parameters)
:java.lang.reflect.ParameterizedType() //-> 这个是带有泛型参数的类型!
泛型父类(Super Classes)
:java.lang.Class#getGenericSuperclass()
泛型接口(Interfaces)
:java.lang.Class#getGenericInterfaces();
泛型申明(Generics Declaration)
:java.lang.reflect.GenericDeclaration
- 泛型擦写(Generics Erase)
public static void main(String[] args) {
System.out.println(StringList.class.getSuperclass().toGenericString());
}
class StringList extends ArrayList<String>{
}
输出结果:
public class java.util.ArrayList<E>
public static void main(String[] args) {
System.out.println(StringList.class.getGenericSuperclass().toString());
}
class StringList extends ArrayList<String>{
}
输出结果:
java.util.ArrayList<java.lang.String>
以上的举例其实就是想说明一点:泛型其实在编译的时候,类型还是会被保存在字节码文件当中,但是当运行的时候类型就会被擦写掉了,object类型的都是可以插入的.
public class StringDemo {
public static void main(String[] args) throws Exception {
//类所在的classpath物理路径
/*System.out.println(scanBasePackageClass.getProtectionDomain());
System.out.println("==============");
System.out.println(scanBasePackageClass.getProtectionDomain().getPermissions());
System.out.println("==============");
System.out.println(scanBasePackageClass.getProtectionDomain().getCodeSource());
System.out.println("==============");
System.out.println(scanBasePackageClass.getProtectionDomain().getCodeSource().getLocation());*/
// 模仿 Spring 类扫描
// 通过标准方式 - Java 反射
// 通过 ASM -
Class<?> scanBasePackageClass = StringDemo.class;
String scanBasePackage = scanBasePackageClass.getPackage().getName();
// 类所在的 class path 物理路径
String classPath = getClassPath(scanBasePackageClass);
File classPathDirectory = new File(classPath);
File scanBasePackageDirectory = new File(classPathDirectory, scanBasePackage.replace('.', '/'));
// 获取所有的 Class 文件 -> *.class
File[] classFiles = scanBasePackageDirectory.listFiles(file -> {
return file.isFile() && file.getName().endsWith(".class");
});
System.out.println("class path : " + classPath);
System.out.println("scan base package : " + scanBasePackage);
System.out.println("scan class files :" + Stream.of(classFiles).map(File::getName).collect(Collectors.joining(",")));
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
List<Class<?>> targetClasses = new LinkedList<>();
for (File classFile : classFiles) {
String simpleClassName = classFile.getName().substring(0, classFile.getName().lastIndexOf("."));
String className = scanBasePackage + "." + simpleClassName;
// 加载所有类
Class<?> loadedClass = classLoader.loadClass(className);
// 判断是否存在 @Repository 注解
if (loadedClass.isAnnotationPresent(Repository.class)) {
targetClasses.add(loadedClass);
}
}
// 判断 targetClasses 是否 CrudRepository 类的实现类
targetClasses.stream()
.filter(StringDemo::isConcrete) // 筛选具体类
.filter(StringDemo::isCrudRepositoryType) // 筛选 CrudRepository 类的实现类
.forEach(type -> { // CrudRepository 泛型类型
Type[] superInterfaces = type.getGenericInterfaces(); // 获取泛型父接口
Stream.of(superInterfaces)
.filter(t -> t instanceof ParameterizedType)// 判断接口是否 ParameterizedType 类型
.map(t -> (ParameterizedType) t) // 转换为 ParameterizedType
.filter(parameterizedType -> CrudRepository.class.equals(parameterizedType.getRawType())) // 判断 ParameterizedType 原始类型是否 CrudRepository
.forEach(parameterizedType -> {
// 获取第一个泛型参数
String argumentTypeName = parameterizedType.getActualTypeArguments()[0].getTypeName();
try {
System.out.println(classLoader.loadClass(argumentTypeName));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
});
}
private static boolean isCrudRepositoryType(Class<?> type) {
return CrudRepository.class.isAssignableFrom(type);
}
private static boolean isConcrete(Class<?> type) {
return !Modifier.isAbstract(type.getModifiers());
}
private static String getClassPath(Class type) {
return type.getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);
}
}
interface CrudRepository<E extends Serializable> {
// declared methods...
}
@Repository
class UserRepository implements Comparable<UserRepository>, // getGenericInterfaces[0] = ParameterizedType ->
// ParameterizedType.rawType = Comparable
// ParameterizedType.getActualTypeArguments()[0] = UserRepository
CrudRepository<User>, // getGenericInterfaces[1] = ParameterizedType -> ParameterizedType.rawType = CrudRepository
// ParameterizedType.rawType = CrudRepository
// ParameterizedType.getActualTypeArguments()[0] = User
Serializable { // getGenericInterfaces[2] = Class -> isInterface() == true
@Override
public int compareTo(UserRepository o) {
return 0;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Repository {
String value() default "";
}
class User implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
类成员
- 字段(字段本身是元数据,包含的内容是数据或称为属性)
类字段
对象字段
- 方法(Methods)(描述对象行为的契约或者实现)方法唯一约束是方法签名
归属(定义所在)
访问修饰符(public)
访问性(Accessibility)
:public protected private
属性
:
static final volatile transient//(反持久化的)
Private transient int hashCode;//(缓存hashCode)配合serializable -> 属性不会被序列化
Private static trasient int hashCode; //这个是没有意义的,因为static是跟着类走的,类是决定结构的 -> static就是transient.序列化和反序列化都是跟着对象走的
//方法:
static final synchronize native abstract strictfp
Strictfp float add(float a , float b){
Return a+b;
}
`返回类型(Return type)`
`方法名称(method name)`
`方法参数(method parameters)`
`方法异常列表(method throws)`
- 构造器(Constructors)
归属(定义所在)
访问修饰符(public)
构造器名称(construct name = Class Names)
构造器参数(construct parameters)
构造器异常列表(method throws)
- 成员(Members):java.lang.reflect.Members
- 可执行成员(Executable):java.lang.reflect.Executable(Java8新增的内容)