public class Test01 extends Object{ //@Override 重写的注解 @Override public String toString() { return super.toString(); } //@Deprecated,不推荐程序员使用,但是可以使用,或者存在更好的方式 @Deprecated public static void test(){ System.out.println("Deprecated"); } //@SuppressWarnings 镇压警告 @SuppressWarnings("all") public void thest02(){ List list = new ArrayList<>(); } public static void main(String[] args) { test(); } }
//定义一个注解 //Target 表示我们的注解可以用在哪些地方 @Target(value = {ElementType.METHOD,ElementType.TYPE}) //Retention 表示我们的的注解在什么地方还有效 //runtime>class>sources @Retention(value = RetentionPolicy.RUNTIME) //Document 表示是否将我们的注解生成在Javadoc中 @Documented //Inherited 子类可以继承父类的注解 @interface MyAnnotation{ }
用 @interface 自定义注解,public @interface 注解名 { 定义内容 },自动继承java.lang.annotation.Annotation接口。
分析:
注解元素必须要有值,一般用空字符串和0作默认值,-1作默认值,代表不存在。
通过default来声明参数的默认值。
若只有一个参数成员,参数名一般为value,可以省略value。
方法的名称就是参数的名称,返回值类型就是参数的类型,(返回值类型只能是基本类型,Class,String,enum)
//自定义注解 public class Test03 { //注解可以显式赋值,如果没有默认值,就必须给注解赋值,不显示则是默认值。 @MyAnnotation2(name = "张三") public void test(){ } @MyAnnotation3("李四")//只有一个参数,参数成员为value 可以省略value public void test2(){ } } @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //注解的参数:参数类型 + 参数名 + () String name();//没有默认值 String name01() default ""; int age() default 0; int id() default -1;//如果默认值为负一,代表不存在。 String[] school() default {"花园宝宝","花园宝宝乐园"}; } @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ String value(); }
public class Test02 { public static void main(String[] args) throws ClassNotFoundException { //通过反射获取类的class对象 Class c1 = Class.forName("com.feng.reflection.User"); System.out.println(c1); Class c2 = Class.forName("com.feng.reflection.User"); Class c3 = Class.forName("com.feng.reflection.User"); Class c4 = Class.forName("com.feng.reflection.User"); //一个类在加载后,类的整个结构都被会封装在Class对象中。 System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode());//c2 c3 c4 hashcode相同 //一个类在内存中只有一个Class对象 } } //实体类 class User{ private String name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } }
//得到Class类的几种方式 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()); //方式二:forname获得 Class c2 = Class.forName("com.feng.reflection.Student0"); 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类的常用方法,如: //获得父类类型 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 = "老师"; } }
public 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 int a[] = new int[10]; int b[] = new int[100]; System.out.println(a.getClass().hashCode()); System.out.println(b.getClass().hashCode()); } }
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>(){ System.out.println("A类静态代码块初始化"); m = 300; m = 100; } m = 100; */ } } class A{ static { System.out.println("A类静态代码块初始化"); m = 300; } static int m = 100; public A() { System.out.println("A类的无参构造器初始化"); } }
//类什么时候会初始化 public class Test06 { static { System.out.println("Main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { //1.主动引用:对象 //Son son = new Son(); Main类被加载 父类被加载 子类被加载 //2.反射也会产生主动引用 //Class.forName("com.feng.reflection.Son"); Main类被加载 父类被加载 子类被加载 //被动引用1 //System.out.println(Son.b); Main类被加载 父类被加载 2 //被动引用2 Son[] array = new Son[5]; //Main类被加载 } } class Father{ static int b = 2; static { System.out.println("父类被加载"); } } class Son extends Father{ static int m = 100; static final int M = 1; static { System.out.println("子类被加载"); m = 300; } }
类加载器的作用
类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类加载器的作用:来把类(class)装载进内存中。
引导类加载器:用C++编写,JVM自带的类加载器,负Java平台核心库。
扩展类加载器:使用java代码实现,主要加载jre/lib/ext/ 下的扩展类库。
系统类加载器:使用java代码实现,加载classpath目录下的类。
自定义类加载器:继承ClassLoader类实现自定义类加载器。
自底向上检查类是否装载,自顶向下尝试加载类。
public class Test07 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2 //获取系统类的加载器的父类加载器-->扩展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent);//sun.misc.Launcher$ExtClassLoader@74a14482 //获得扩展类加载器的父类加载器-->根加载器(C/C++) ClassLoader parent1 = parent.getParent(); System.out.println(parent1);//null //测试当前类是哪个加载器加载的 ClassLoader classLoader = Class.forName("com.feng.reflection.Test07").getClassLoader(); System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2 //测试JDK内置的类是哪个加载器加载的 classLoader = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader);//null //如何获得系统类加载器的加载路径 System.out.println(System.getProperty("java.class.path")); //双亲委派机制 } }
getName():获得包名 + 类名,getSimpleName():获得类名。
getFields():只能找到public属性,getDeclaredFields():找到全部的属性,getDeclaredField(“name”):获得指定属性的值。
getMethods():获得本类及其父类的全部public方法,getDeclaredMethods():获得本类的所有方法,
getMethod(“setName”, String.class):获得指定的方法(“方法名字”,参数类型)。
getConstructors():获得构造器,getDeclaredConstructor(String.class, int.class, int.class):获得指定有参构造器。
public class Test08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.feng.reflection.User"); //获得类的名字 System.out.println(c1.getName());//获得包名 + 类名 System.out.println(c1.getSimpleName());//获得类名 System.out.println("========================="); //获得类的属性 Field[] fields = c1.getFields();//只能找到public属性 fields = c1.getDeclaredFields();//找到全部的属性 for (Field field : fields) { System.out.println(field); } //获得指定属性的值 Field name = c1.getDeclaredField("name"); System.out.println("指定:" + name); System.out.println("========================="); //获得类的方法 Method[] methods = c1.getMethods();//获得本类及其父类的全部public方法 for (Method method : methods) { System.out.println("正常的:" + method); } methods = c1.getDeclaredMethods();//获得本类的所有方法 for (Method method : methods) { System.out.println("getDeclaredMethods:"+method); } //获得指定方法 //重载 Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); System.out.println("指定:" + getName); System.out.println("指定:" + setName); System.out.println("========================="); //获得指定的构造器 Constructor[] constructors = c1.getConstructors();//获得public方法 for (Constructor constructor : constructors) { System.out.println(constructor); } constructors = c1.getDeclaredConstructors();//获得本类全部方法 for (Constructor constructor : constructors) { System.out.println(constructor); } //获得指定的构造器 Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); System.out.println("指定:" + declaredConstructor); } }
public class Test09 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("com.feng.reflection.User"); //构造一个对象 User user1 = (User) c1.newInstance();//本质是调用了无参构造器 System.out.println(user1); //通过构造器创建对象 Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user2 = (User) constructor.newInstance("张三", 001, 20); System.out.println(user2); System.out.println("===================================="); //通过反射调用普通方法 User user3 = (User) c1.newInstance(); //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); //invoke : 激活的意思 //(对象,“方法的值”) setName.invoke(user3, "张三"); System.out.println(user3.getName()); System.out.println("===================================="); //通过反射操纵属性 User user4 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); //不能直接操作私有属性,我们需要关闭程序的安全检测,通过方法或者属性的setAccessible(true) name.setAccessible(true); name.set(user4,"李四"); System.out.println(user4.getName()); } }
//普通方式调用 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 NoSuchMethodException, IllegalAccessException, InvocationTargetException { test01(); test02(); test03(); } } 普通方式执行10亿次:4ms 反射方式执行10亿次:2205ms 关闭检测执行10亿次:1063ms-->提高效率
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 method = Test11.class.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 = Test11.class.getDeclaredMethod("test02",null); Type genericReturnType = method.getGenericReturnType(); if(genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } }
//获取注解信息 反射操作注解 public class Test12 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("com.feng.reflection.student2"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解的value的值 TableFeng tableFeng = (TableFeng)c1.getAnnotation(TableFeng.class); String value = tableFeng.value(); System.out.println(value); //获得类指定的注解 Field name = c1.getDeclaredField("name"); FieldFeng annotation = name.getAnnotation(FieldFeng.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @TableFeng("db_student") class student2 { @FieldFeng(columnName = "db_id", type = "int", length = 10) private int id; @FieldFeng(columnName = "db_age", type = "int", length = 10) private int age; @FieldFeng(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 TableFeng { String value(); } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) //属性的注解 @interface FieldFeng { String columnName();//列名 String type();//类型 int length();//长度 }