package com.thj.annotation;// 什么是注解public class Test01 extends Object{ // @Override 重写的注解 @Override public String toString() { return super.toString(); }}package com.thj.annotation;import java.util.ArrayList;import java.util.List;// 什么是注解public class Test01 extends Object{ // @Override 重写的注解 @Override public String toString() { return super.toString(); } // 不推荐使用的方法 @Deprecated public void test(){ System.out.println("Deprecated"); } @SuppressWarnings("all") public void test02(){ List list = new ArrayList(); } public static void main(String[] args) { Test01 test01 = new Test01(); test01.test(); }}package com.thj.annotation;import java.lang.annotation.*;// 测试元注解@MyAnnotationpublic class Test02 { @MyAnnotation public void test(){ }}// 定义一个注解// Target 表示我们的注解可以用在那些地方。@Target(value = {ElementType.METHOD,ElementType.TYPE})// Retention表示我们注解在哪里有效// runtime>class>sources@Retention(value = RetentionPolicy.RUNTIME)// Document 表示是否把注解生成到JavaDoc中@Documented// Inherited 子类可以继承父类的注解@Inherited @interface MyAnnotation{}使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:
package com.thj.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(name = "thj") public void test(){} // value可以省略 @MyAnnotation3("thj") public void test2(){}}@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation2{ // 注解的参数: 参数类型+参数名() String name() default ""; int age() default 0; int id() default -1; // 如果默认值为-1,代表不存在.indexof,如果找不到返回-1 String[] school() default {"信阳学院"};}@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation3{ String value();}静态VS动态语言:
动态语言:
静态语言:
Java Reflection
Java反射的优缺点:
优点:可以实现动态创建对象和编译,体现出很大的灵活性
缺点:对性能有影响。慢。
package com.thj.reflection;// 什么叫反射public class Test02 { public static void main(String[] args) throws ClassNotFoundException { // 通过反射获取类的Class对象 Class C1 = Class.forName("com.thj.reflection.User"); System.out.println(C1); Class C2 = Class.forName("com.thj.reflection.User"); Class C3 = Class.forName("com.thj.reflection.User"); Class C4 = Class.forName("com.thj.reflection.User"); // 一个类在内存中只有一个Class对象 // 一个类被加载后,类的整个结构都会被封装在Class对象中。 System.out.println(C2.hashCode()); System.out.println(C3.hashCode()); System.out.println(C4.hashCode()); }}// 实体类:pojo/entityclass User{ private String name; private int age; private int id; public User() { } public User(String name, int age, int id) { this.name = name; this.age = age; this.id = id; } public String getName() { return name; } public void setName(String name) { 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; }}可以得到:某个类的属性,方法和构造器,某个类到底实现了那个接口。
获取Class类的实例:
package com.thj.reflection;// 测试类的创建方式有那些public class Test03 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("这个人是:"+person.name); // 方式一:通过对象获得 Class c1 = person.getClass(); System.out.println(c1.hashCode()); // 方式二:通过路径获得 Class c2 = Class.forName("com.thj.reflection.Person"); System.out.println(c2.hashCode()); // 方式三,通过类名.class获得 Class c3 = Student.class; System.out.println(c3.hashCode()); // 方式四:基本类型的包装类.Type Class c4 = Integer.TYPE; System.out.println(c4); // 获得父类类型 Class c5 = c1.getSuperclass(); System.out.println(c5); }}class Person{ public String name; public Person(){ } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; }}class Student extends Person{ public Student(){ this.name = "学生"; }}class Teacher extends Person { public Teacher() { this.name = "老师"; }}package com.thj.reflection;import java.lang.annotation.ElementType;// 所有类型的Classpublic class Test04 { public static void main(String[] args) { Class c1 = Object.class; // 类 Class c2 = Comparable.class; // 接口 Class c3 = String[].class; // 一维数组 Class c4 = int[][].class; // 二维数组 Class c5 = Override.class; // 注解 Class c6 = ElementType.class; // 枚举 Class c7 = Integer.class; // 基本数据类型 Class c8 = void.class; // void 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。 }}package com.thj.reflection;public class Test05 { public static void main(String[] args) { A a = new A(); System.out.println(a.m); /* 1.加载到内存,产生一个类对应Class对象 2.链接,链接结束后 m=0 3.初始化: <clinit>(){ sout; m=300; m=100; } */ }}class A{ static { System.out.println("A类静态代码块初始化"); m = 300; } static int m = 100; public A(){ System.out.println("A类的无参构造器初始化"); }}package com.thj.reflection;// 测试类什么时候会初始化public class Test06 { static { System.out.println("main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { // 主动引用 // Son son = new Son(); // 反射也会产生主动引用 // Class.forName("com.thj.reflection.Son"); // 不会产生类的引用的方法 // System.out.println(Son.b); // Son[] array = new Son[5]; System.out.println(Son.M); }}class Father{ static int b = 2; static { System.out.println("父类被加载"); }}class Son extends Father{ static { System.out.println("子类被加载"); m = 300; } static int m = 100; static final int M = 1;}package com.thj.reflection;public class Test07 { public static void main(String[] args) throws ClassNotFoundException { // 获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); // 获取系统类加载器的父类加载器——》扩展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); // 获取扩展类加载器的父类加载器--》根加载器(c、c++) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); // 测试当前类是那个加载器加载的 ClassLoader classLoader = Class.forName("com.thj.reflection.Test07").getClassLoader(); System.out.println(classLoader); // 测试jdk内置的类由那个加载器加载 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); // 如何获取系统类加载器可以加载的路径 System.out.println(System.getProperty("java.class.path")); // 双亲委派机制 // 保证安全性,层层检测 }}package com.thj.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;// 获得类的信息public class Test08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.thj.reflection.User"); // 1.获得类的名字 System.out.println(c1.getName()); System.out.println(c1.getSimpleName()); // 2.获得类的属性 // getFileds() 只能获得public属性 Field[] field = c1.getDeclaredFields(); // 找到全部的属性 for (Field field1 : field) { System.out.println(field1); } // 3.获得指定属性的值 Field name = c1.getDeclaredField("name"); System.out.println(name); System.out.println("==============================="); // 4.获得类的方法 Method[] methods = c1.getMethods(); // 获得本类和父类的所有public方法 for (Method method : methods) { System.out.println(method); } Method[] declaredMethods = c1.getDeclaredMethods(); // 获得本类的所有方法 for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } // 5.获得指定方法 // 重载 Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println(getName); System.out.println(setName); // 6.获得指定构造器 Constructor[] constructors = c1.getConstructors(); // public Constructor[] constructors1 = c1.getDeclaredConstructors(); // 全部 for (Constructor constructor : constructors) { System.out.println(constructor); } for (Constructor constructor : constructors1) { System.out.println(constructor); } // 7.获得指定的构造器 Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println("指定:"+declaredConstructor); }}小结:
package com.thj.reflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;// 动态的创建对象,通过反射public class Test09 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { Class c1 = Class.forName("com.thj.reflection.User"); // 获得Class对象 // 构造一个对象 // User user = (User)c1.newInstance(); // 本质上时调用了类的无参构造器 // System.out.println(user); // 通过构造器创建对象// Constructor Constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);// User thj = (User) Constructor.newInstance("thj", 001, 18);// System.out.println(thj); // 通过反射调用方法 User user = (User)c1.newInstance(); // 通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); // invoke :激活 // (对象, “方法的值”) setName.invoke(user,"狂神"); System.out.println(user.getName()); // 通过反射操作属性 User user1 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); // 不能直接操作私有属性,必须关闭程序的安全检测,通过属性或者方法的setAccessible(true)。 name.setAccessible(true); name.set(user1,"狂神2"); System.out.println(user1.getName()); /* 每个method,Filed,Constructor对象都有setAccessible()方法 作用是启动或禁用访问安全检测的开关 */ }}package com.thj.reflection;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;// 分析性能问题public class Test10 { // 普通方式调用 public static void test01(){ User user = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println("普通方式执行10亿次:"+(endTime-startTime)+"ms"); } // 反射方式调用 public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("反射方式执行10亿次:"+(endTime-startTime)+"ms"); } // 反射方式调用,关闭检测 public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName", null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) { getName.invoke(user,null); } long endTime = System.currentTimeMillis(); System.out.println("关闭检测,反射方式执行10亿次:"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { test01(); test02(); test03(); }}通过程序运行时间可以看到,普通方法执行之快,通过反射执行方法将速度变慢了许多,但是,关闭安全检测可以提高一些运行速度。
package com.thj.reflection;import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.Map;import java.util.List;// 通过反射获取泛型public class Test11 { public void test01(Map<String,User> map, List<User> list){ System.out.println("test01"); } public Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method test01 = Test11.class.getMethod("test01", Map.class, List.class); Type[] genericParameterTypes = test01.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 test02 = Test11.class.getMethod("test02", null); Type genericReturnType = test02.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } }}注解挺重要的,尤其在框架的运用上。
package com.thj.reflection;import java.lang.annotation.*;import java.lang.reflect.Field;public class Test12 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("com.thj.reflection.Student2"); // 通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } // 获得注解指定的值(value) Tablethj annotation = (Tablethj)c1.getAnnotation(Tablethj.class); String value = annotation.value(); System.out.println(value); // 获得类指定的注解 Field name = c1.getDeclaredField("id"); Fieldthj annotation1 = name.getAnnotation(Fieldthj.class); System.out.println(annotation1.columnName()); System.out.println(annotation1.type()); System.out.println(annotation1.length()); }}@Tablethj("db_student")class Student2{ @Fieldthj(columnName = "db_id",type = "int",length = 10) private int id; @Fieldthj(columnName = "db_age",type = "int",length = 10) private int age; @Fieldthj(columnName = "db_name",type = "varchar",length = 3) private String name; public Student2(){ } public Student2(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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 "Student2{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; }}// 类名的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface Tablethj{ String value();}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)// 属性的注解@interface Fieldthj{ String columnName(); String type(); int length();}