注解与反射
内置注解
-
类似于@overrided
元注解
-
@Target 表示注解我们可以用在哪些地方
-
@Retention 表示我们的注解在什么地方还有效 (runtimes>class>sources) 定义了runtime,就在任意地方都有效
-
@Documengted 表示是否将我们的注解生成在JAVAdoc中
-
@Inherited 表示子类可以继承父类的注解
自定义注解
使用@interface可以自定义注解 public @interface 注解名 {注解的参数:参数类型 +参数名();【如果定义的参数没有默认值,那么必须给注解赋值,否则报错;如果默认值为-1,代表不存在】};
一般自定义注解都是先将元注解:
@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)进行定义
反射(Reflection)
-
通过反射获取class类
//通过反射获取类的class对象
Class c1=Class.forName("User");
System.out.println(c1);
//定义多个class类指向同一个包
Class c2=Class.forName("User");
Class c3=Class.forName("User");
Class c4=Class.forName("User");
//一个类在内存中只有一个class对象,都是一个hashcode地址
//一个类被加载之后,类的整个结构都会被封装在class对象中
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
-
class类的创建方式
Person person = new Student();
System.out.println("这个人是:"+person.name);
//方式一:通过对象,获取class类
Class c1=person.getClass();
System.out.println(c1.hashCode());
//方式二:通过forName获取
Class c2=Class.forName("Student");
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对象
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());
System.out.println(a.hashCode());
-
类加载内存分析对象
(1)java文件通过jdk编译成class文件,然后通过类加载器将class文件加载在内存中,在堆中生成一个这个类对应的class对象
(2)链接,链接回在方法去中将类对象中的静态方法和常量进行初始值的赋值,然后进行分配
(3)初始化(clinit),会将数据进行加载和相同代码的合并
-
如何类才会进行初始化
1.主动引用(Son s1=new Son();)
2.反射也会产生主动引用(class.forName(包名))
3.调用父类的静态变量不会引起之类的初始化
4.常量的引用不会引起子类与父类的引用
-
类加载器
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取系统类加载器的父类加载器-->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
//获取扩展类加载器的父类加载器-->根加载器(用C、C++编写的)
ClassLoader parent1 = systemClassLoader.getParent();
//测试当前类是那个加载器加载的
ClassLoader classLoader = Class.forName("Test").getClassLoader();
System.out.println(classLoader);
//测试JDK内置类是谁加载的
classLoader=Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
//如何获取系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path")); -
如何通过反射获取类的信息
Class c1 = Class.forName("Person");
//获取类的名字
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);
//获取类的方法
Method[] methods=c1.getMethods(); //获取本类及其父类的全部public方法
methods=c1.getDeclaredMethods(); //获取本类的所有方法
//获取指定的方法
//因为方法有重载的机制,所以如果方法有参数,就需要传递参数
Method method=c1.getMethod("toString");
//获取指定类的构造器
Constructor[] constructors=c1.getConstructors();
constructors=c1.getDeclaredConstructors();
//获取指定有参的构造器
Constructor constructor=c1.getDeclaredConstructor(String.class); -
通过class对象可以干什么?
//获得class对象
Class c1 = Class.forName("Person");
Person person = (Person)c1.newInstance();//本质上是调用了类的无参构造器;没有数据
System.out.println(person);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class);
Person person1 = (Person) constructor.newInstance("quchaunming");
System.out.println(person1);
//通过反射调用方法
Person person = (Person) c1.newInstance();
//通过反射获取一个方法
Method method = c1.getDeclaredMethod("setName",String.class);
//激活该对象中的方法
method.invoke(person,"quchuanming");
System.out.println(person.getName());
//通过反射调用属性
Person person1 = (Person) c1.newInstance();
Field field = c1.getDeclaredField("name");
//私有的属性你可以获得到,但是不能直接操作,需要关闭程序的安全检测。属性或者方法的setAccessible(true)
field.setAccessible(true);
field.set(person1,"qu2");
System.out.println(person1.getName());
-
创建对象的正常方法和反射方法的性能对比
//普通方式调用
public static void testprofile1() {
Person p1 = new Person();
long starttime=System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
p1.getName();
}
long enddtime = System.currentTimeMillis();
System.out.println("普通方法执行花费:"+(enddtime-starttime));
}
//反射方式调用
public static void testprofile2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("Person");
Person p1 = (Person)c1.newInstance();
Method method = c1.getDeclaredMethod("getName",null);
long starttime=System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
method.invoke(p1,null);
}
long enddtime = System.currentTimeMillis();
System.out.println("反射方式调用花费:"+(enddtime-starttime));
}
//反射方式调用 关闭检测
public static void testprofile3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("Person");
Person p1 = (Person)c1.newInstance();
Method method = c1.getDeclaredMethod("getName",null);
method.setAccessible(true);
long starttime=System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
method.invoke(p1,null);
}
long enddtime = System.currentTimeMillis();
System.out.println("反射方式调用 关闭检测:"+(enddtime-starttime));
} -
反射操作泛型
Method method = Test.class.getDeclaredMethod("Test1",Map.class,List.class);
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
System.out.println("||"+type);
if(type instanceof ParameterizedType){
Type[] actural = ((ParameterizedType)type).getActualTypeArguments();
for (Type type1 : actural) {
System.out.println(type1);
}
}
}
Method method2 = Test.class.getDeclaredMethod("Test2",null);
Type genericReturnType = method2.getGenericReturnType();
System.out.println("||"+genericReturnType);
if(genericReturnType instanceof ParameterizedType){
Type[] actural = ((ParameterizedType)genericReturnType).getActualTypeArguments();
for (Type type1 : actural) {
System.out.println(type1);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//通过反射获取泛型
public void Test1(Map<String,Person> map, List<String> list){
System.out.println("Test1");
}
public Map<String,Person> Test2(){
System.out.println("Test1");
return null;
} -
反射操作注解
Class c1 = Class.forName("Person"); Annotation[] annotations = c1.getAnnotations();//获取完整注解名字 for (Annotation annotation : annotations) { System.out.println(annotation); } //获取指定注解中的值 Tablequ tablequ = (Tablequ) c1.getAnnotation(Tablequ.class); System.out.println(tablequ.value()); Field field = c1.getDeclaredField("name"); Fieldqu fieldqu = field.getAnnotation(Fieldqu.class); System.out.println(fieldqu.columnName()); System.out.println(fieldqu.length()); System.out.println(fieldqu.type()); //定义一个实体类 @Tablequ("db_person") class Person{ @Fieldqu(columnName = "db_name",type = "varchar",length = 200) public String name; } //类名的注释 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tablequ{ String value(); } //类名的注释 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Fieldqu{ String columnName(); String type(); int length(); }
浙公网安备 33010602011771号