注解和反射
注解和反射
注解
-
机器可以识别,和注释不同,注释是给人看的
-
内置注解
一共三种@Override,@Deprecated,@SuppressWarnings()
@SuppressWarnings("") public class Test01 extends Thread{ //重写父类方法 @Override public void run() { super.run(); } //废弃,可以用但不建议 @Deprecated public void say(){ } //去掉提醒 @SuppressWarnings("all") public void play(){ int i = 0; } } -
元注解
-
注解其他的注解,解释说明其他注解
-
- Target表示该注解的作用范围
- Retention表示该注解的有效的敌方,source表示只在源码生效,一般用runtime,运行时
- Documented表示是否将注解记录在javadoc中
- Inherited表示注解是否可被继承
package com.zhm.annotation; import java.lang.annotation.*; @MyAnnotation public class Test02 { @MyAnnotation public static void main(String[] args) { } } //Target表示该注解的作用范围 @Target(value = {ElementType.TYPE,ElementType.METHOD}) //Retention表示该注解的有效的敌方,source表示只在源码生效,一般用runtime,运行时 //Runtime>class>source @Retention(value = RetentionPolicy.RUNTIME ) //Documented表示是否将注解记录在javadoc中 @Documented //Inherited表示注解是否可被继承 @Inherited @interface MyAnnotation{ } -
自定义注解
package com.zhm.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class Test03 { @MyAnnotation2(name3 = {"牛逼","牛逼在哪"},age3 = 1) public static void main(String[] args) { } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //注解的参数: 参数类型 + 参数名 +() //加default可以初始化默认值 //如果参数只有一个,可以用value命名,调用时可以省略value String name() default "zza"; String[] name2() default "azaz"; String[] name3(); int age() default 0; int age2() default -1; int age3(); }
反射
基本概念
-
JavaScript,Python为动态语言
-
java,c,c++为静态语言
-
动态和静态语言区别在于运行时,代码可以根据某种条件改变自身结构
-
java通过反射可以称为”准动态语言“
-
-
一个类在内存中只有一个Class对象
-
一个类被加载后,类的整个结构都会封装在Class对象中
package com.zhm.reflection; public class Test01 { public static void main(String[] args) throws ClassNotFoundException { Class aClass = Class.forName("com.zhm.reflection.Student"); System.out.println(aClass); Class aClass1 = Class.forName("com.zhm.reflection.Student"); Class aClass2 = Class.forName("com.zhm.reflection.Student"); Class aClass3 = Class.forName("com.zhm.reflection.Student"); System.out.println(aClass1.hashCode()); System.out.println(aClass2.hashCode()); System.out.println(aClass3.hashCode()); } } //实体类 class Student{ private int age; private String name; public Student() { } public Student(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return super.toString(); } }
获得Class对象方法
-
package com.zhm.reflection; public class Test02 { public static void main(String[] args) throws ClassNotFoundException { //三种获得类的Class对象 //1用一个类的对象.getclass Person person = new Teacher(); Class<? extends Person> c1 = person.getClass(); System.out.println(c1.hashCode()); //2用Class.forName(类的路径) Class<?> c2 = Class.forName("com.zhm.reflection.Teacher"); System.out.println(c2.hashCode()); //3用类名.class Class<Teacher> c3 = Teacher.class; System.out.println(c3.hashCode()); //补充4基本类型的包装类内置Type属性 Class<Integer> c4 = Integer.TYPE; System.out.println(c4); //获得父类类型 Class<?> c5 = c1.getSuperclass(); System.out.println(c5); } } class Person{ String name; public Person() { } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Teacher extends Person{ public Teacher() { this.name = "teacher"; } } class Fucker extends Person{ public Fucker() { this.name = "fucker"; } }
所有类型的Class对象
package com.zhm.reflection;
import java.lang.annotation.ElementType;
public class Test03 {
public static void main(String[] args) {
//所有类型的Class对象
Class<Object> c1 = Object.class;//类
Class<String[]> c2 = String[].class;//一维数组
Class<int[][]> c3 = int[][].class;//二维数组
Class<Runnable> c4 = Runnable.class;//接口
Class<Override> c5 = Override.class;//注解
Class<Void> c6 = void.class;//void
Class<Integer> c7 = Integer.class;//基本数据类型
Class<ElementType> c8 = ElementType.class;//enum类型
Class<Class> c9 = Class.class;//Class类
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
//只要元素类型和维度(一维数组就是一维)一样,就是同一个Class对象
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
类加载内存分析
package com.zhm.reflection;
public class Test04 {
public static void main(String[] args) {
/*
三个阶段
1.加载,在方法区加载Test04类和A类的数据(静态变量,静态方法,常量池子,代码)
在堆中创建一个java.lang.Class类对象代表Test04类,一个java.lang.Class类对象代表A类
Class对象代表类的结构
2.链接,在栈中分配内存,创建静态对象,初始化(m=0)
运行main方法
A a,创建A类对象a,a找到A类Class对象,对a的相关数据修改赋值
3.初始化,jvm调用
<clinut>(){
System.out.println("我是A的静态代码块");
m = 20;
m = 10;
}
合并static代码,执行,m=10
*/
A a = new A();
System.out.println(a.m);
}
}
class A{
static {
System.out.println("我是A的静态代码块");
m = 20;
}
static int m = 10;
public A() {
System.out.println("我是A的无参构造");
}
}
类的初始化的情况
package com.zhm.reflection;
public class Test05 {
static {
System.out.println("Main方法被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
//主动引用
//1new一个对象,会加载子类,如果父类没被加载,则先父再子
// Son son = new Son();
//2通过反射,会加载子类,如果父类没被加载,则先父再子
// Class<?> c1 = Class.forName("com.zhm.reflection.Son");
//不会产生类的引用
//1调用静态方法或者静态变量,只会加载定义静态的类
// System.out.println(Son.age);
//2创建对象数组,不会加载类,本质只是开个空间进行命名
// Son[] sons = new Son[10];
//3调用常量,也不会加载类,因为常量在链接阶段已经调入常量池中
System.out.println(Son.M);
}
}
class Father{
static int age = 10;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
}
static final int M = 19;
}
类加载器
-
类加载器(装载器)把字节码文件加载到内存,把静态数据放入方法区中
-
类加载器jvm规定三个类型
-
- 引导类加载器,最底层,c++编写,jvm自带用来装载核心类库rt.jar,无法直接获取
- 扩展类加载器,jre/lib/ext等扩展类的加载器
- 系统类(用户类)加载器,用户定义,java.class.path目录,是最常用的
package com.zhm.reflection; public class Test06 { public static void main(String[] args) throws ClassNotFoundException { //获得系统加载器(用户) ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //获得系统加载器父类加载器,拓展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); //获得扩展类加载器父类,根加载器 ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //测试当前类用哪个类加载器加载 //用户自定义类会用系统加载器 ClassLoader classLoader = Class.forName("com.zhm.reflection.Test06").getClassLoader(); System.out.println(classLoader); //jdk内置(lang包)的类会用根加载器 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); //获取类加载器可以加载的路径 //在路径内才能加载 System.out.println(System.getProperty("java.class.path")); /* F:\Environment\java\jdk1.8\jre\lib\charsets.jar; F:\Environment\java\jdk1.8\jre\lib\deploy.jar; F:\Environment\java\jdk1.8\jre\lib\ext\access-bridge-64.jar; F:\Environment\java\jdk1.8\jre\lib\ext\cldrdata.jar; F:\Environment\java\jdk1.8\jre\lib\ext\dnsns.jar; F:\Environment\java\jdk1.8\jre\lib\ext\jaccess.jar; F:\Environment\java\jdk1.8\jre\lib\ext\jfxrt.jar; F:\Environment\java\jdk1.8\jre\lib\ext\localedata.jar; F:\Environment\java\jdk1.8\jre\lib\ext\nashorn.jar; F:\Environment\java\jdk1.8\jre\lib\ext\sunec.jar; F:\Environment\java\jdk1.8\jre\lib\ext\sunjce_provider.jar; F:\Environment\java\jdk1.8\jre\lib\ext\sunmscapi.jar; F:\Environment\java\jdk1.8\jre\lib\ext\sunpkcs11.jar; F:\Environment\java\jdk1.8\jre\lib\ext\zipfs.jar; F:\Environment\java\jdk1.8\jre\lib\javaws.jar; F:\Environment\java\jdk1.8\jre\lib\jce.jar; F:\Environment\java\jdk1.8\jre\lib\jfr.jar; F:\Environment\java\jdk1.8\jre\lib\jfxswt.jar; F:\Environment\java\jdk1.8\jre\lib\jsse.jar; F:\Environment\java\jdk1.8\jre\lib\management-agent.jar; F:\Environment\java\jdk1.8\jre\lib\plugin.jar; F:\Environment\java\jdk1.8\jre\lib\resources.jar; F:\Environment\java\jdk1.8\jre\lib\rt.jar; F:\ava\project\annotation and reflect\out\production\annotation and reflect; F:\ava\programs\IntelliJ IDEA 2022.3.1\lib\idea_rt.jar */ } }双亲委派机制
自己定义的类和jdk官方定义的类同名,会向上(父类)一步一步检测有没有相同类,为了安全性,有相同就不会用自己定义的
通过类的Class对象获取类的所有信息
-
可以获取类的属性,方法,构造器,等等
package com.zhm.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test07 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class<?> c1 = Class.forName("com.zhm.reflection.Student"); //获得包名+类名 System.out.println(c1.getName()); //获得类名 System.out.println(c1.getSimpleName()); Test01.fgx(); //获得public属性 Field[] fields = c1.getFields(); for (Field field : fields) { System.out.println(field); } //获得全部属性,包括私有属性 fields = c1.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } //获得指定属性 System.out.println(c1.getDeclaredField("name")); Test01.fgx(); //获得全部public方法,包括父类的 Method[] methods = c1.getMethods(); for (Method method : methods) { System.out.println(method); } //获得全部方法包括私有,不包括父类 methods = c1.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } //获得指定方法,传入方法名和参数类型的类的Class对象 System.out.println(c1.getDeclaredMethod("getAge",null)); System.out.println(c1.getDeclaredMethod("setAge", int.class)); Test01.fgx(); //获得public构造器 Constructor<?>[] constructors = c1.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor); } //获得全部构造器,包括private constructors = c1.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor); } //获得指定构造器 System.out.println(c1.getDeclaredConstructor(int.class, String.class)); } }
通过类的Class对象动态创建对象执行方法
- 创建对象
- c1.newInstance方法,本质无参
- 通过c1获取有参构造,newInstance方法传入初始化值
- 获取方法
- 通过c1创建对象,直接调用非private
- 通过c1创建对象,再通过c1获取方法,再用invoke方法
- 获取字段
- 通过c1创建对象,直接获取非private
- 通过c1创建对象,再通过c1获取字段,再用set方法
- 如果想要获取private的属性和方法和构造器,需要setAccessible方法设置为true,关闭安全检测开关
package com.zhm.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> c1 = Class.forName("com.zhm.reflection.Student");
//通过学生类的Class对象,创建学生类的对象
//1 本质是调用无参构造
Student s1 = (Student) c1.newInstance();
System.out.println(s1);
//2 通过Class对象获取有参构造,再调用newInstance
Constructor<?> constructor = c1.getDeclaredConstructor(int.class, String.class);
Student s2 = (Student) constructor.newInstance(10,"xiaoming");
System.out.println(s2);
//通过Class对象获取方法
Student s3 = (Student) c1.newInstance();
Method setAge = c1.getDeclaredMethod("setAge", int.class);
setAge.invoke(s3,101);
System.out.println(s3.getAge());
//通过Class对象获取,修改数据
Student s4 = (Student) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(s4,"xiaohong");
System.out.println(name.get(s4));
System.out.println(s4.getName());
}
}
反射和普通方法效率对照
package com.zhm.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test09 {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
test01();
test02();
test03();
}
public static void test01(){
long startTime = System.currentTimeMillis();
Student student = new Student();
for (int i = 0; i < 10_0000_0000; i++) {
student.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通执行10亿次需要"+(endTime-startTime)+"ms");
}
public static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
long startTime = System.currentTimeMillis();
Student student = new Student();
Class<Student> c1 = Student.class;
Method getName = c1.getDeclaredMethod("getName", null);
for (int i = 0; i < 10_0000_0000; i++) {
getName.invoke(student,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射执行10亿次需要"+(endTime-startTime)+"ms");
}
public static void test03() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
long startTime = System.currentTimeMillis();
Student student = new Student();
Class<Student> c1 = Student.class;
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
for (int i = 0; i < 10_0000_0000; i++) {
System.out.println(getName.invoke(student, null));
}
long endTime = System.currentTimeMillis();
System.out.println("关闭安全检查的反射执行10亿次需要"+(endTime-startTime)+"ms");
}
}
通过反射获得泛型
- getGenericParameterTypes 获得泛型传入参数类型
- ParameterizedType 参数化类型(Collection
) - getActualTypeArgument 获得实际类型参数
- getGenericReturnType 获得泛型返回类型
package com.zhm.reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
//反射操作泛型
public class Test10 {
public static void main(String[] args) throws NoSuchMethodException {
Class<Test10> c1 = Test10.class;
Method method = c1.getDeclaredMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
method = c1.getDeclaredMethod("test02");
Type genericParameterType = method.getGenericReturnType();
System.out.println(genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
public void test01(Map<String,Student> map, List<Student> list){
System.out.println("test01");
return;
}
public List<Student> test02(){
System.out.println("test02");
return null;
}
}
反射注解结合,通过反射获取注解信息
package com.zhm.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Test11 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class<?> c1 = Class.forName("com.zhm.reflection.Student2");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
Tablezhu annotation = (Tablezhu) c1.getAnnotation(Tablezhu.class);
String value = annotation.value();
System.out.println(value);
Field name = c1.getDeclaredField("name");
Annotation[] annotation1 = name.getAnnotations();
for (Annotation annotation2 : annotation1) {
System.out.println(annotation2);
}
Fieldzhu annotation2 = (Fieldzhu) name.getAnnotation(Fieldzhu.class);
System.out.println(annotation2.cloumnName());
System.out.println(annotation2.length());
System.out.println(annotation2.type());
}
}
//定义实体类
@Tablezhu("db_Student")
class Student2{
@Fieldzhu(length = 10,cloumnName = "db_age",type = "int")
private int age;
@Fieldzhu(length = 10,cloumnName = "db_id",type = "int")
private int id;
@Fieldzhu(length = 3,cloumnName = "db_name",type = "String")
private String name;
public Student2() {
}
public Student2(int age, int id, String name) {
this.age = age;
this.id = id;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student2{" +
"age=" + age +
", id=" + id +
", name='" + name + '\'' +
'}';
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tablezhu{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldzhu{
int length();
String cloumnName();
String type();
}
浙公网安备 33010602011771号