阿小冷学计算机(6)
注解与反射
文章内容来自b站up主,遇见狂神说的视频
本文使来自作者的笔记,留做后面自己观看
注解
(Annotation 注解)
1、什么是注解?
Annotation是从JDK5.0开始引入的新技术
Annotation的作用:
- 不是程序本身,可以对程序作出解释,
- 可以被其他程序(比如:编译器等)读取
Annotation的格式:
- 注解是以 “@注释名”在代码中存在的,还可以添加一些参数值,例如:
- @SuppressWarnings(value=“unchecked”).
Annatation在哪里使用?
- 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些数据的访问
内置注解

public class Test01 extends Object {//@Override 重写的注解@Overridepublic String toString(){return super.toString();}//Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方式@Deprecatedpublic static void test(){System.out.println("Deprecated");}public void test02(){List list = new ArrayList();}public static void main(String[] args) {test();}
}
元注解

package com.axiaoleng1;import java.lang.annotation.*;@MyAnnotation
public class Test02 {public void test(){}
}//定义一个注解
//Target 表示我们的注解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})//Retention 表示我们的注解在什么地方还有效
// runtime>class>sources
@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示是否将我们的注解生成在JAVAdoc中
@Documented//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
自定义注解

package com.axiaoleng1;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 = "阿冷",schools = {"湖南理工","湖理"})@MyAnnotation2()public void test(){}@MyAnnotation3("阿冷")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,代表不存在String[] schools() default {"西部开源","华中科技大学"};
}@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{//一个参数,建议用value命名String value();
}
反射(Reflection)—动态
- 静态语言 vs 动态语言




- 反射相关的主要API
java.lang.Class: 代表一个类
java.lang.reflect.Method: 代表类的方法
java.lang.reflect.Field: 代表类的成员变量
java.lang.reflect.Constructor: 代表类的构造器

package com.axiaoleng1;//什么叫反射
public class Test04 extends Object{public static void main(String[] args) throws ClassNotFoundException {//通过反射类获取类的Class对象Class c1 = Class.forName("com.axiaoleng1.User");System.out.println(c1);Class c2 = Class.forName("com.axiaoleng1.User");Class c3 = Class.forName("com.axiaoleng1.User");Class c4 = Class.forName("com.axiaoleng1.User");//一个类在内存中只有一个Class对象//一个类被加载后,类的整个结构都会被封装在Class对象中System.out.println(c2.hashCode());System.out.println(c3.hashCode());System.out.println(c4.hashCode());}
}//实体类
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;}
}



package com.axiaoleng1;public class Test05 {public static void main(String[] args) throws Exception{Person person = new Student();System.out.println("这个人是:"+person.name);//方式一 :通过对象获得Class c1 = person.getClass();System.out.println(c1.hashCode());//方式二 : forname获得Class c2 = Class.forName("com.axiaoleng1.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 Person{public String name;public Person(){}public Person(String name){this.name=name;}@Overridepublic String toString(){return "Person{"+"name="+ name + '\''+'}';}}class Student extends Person{public Student(){this.name="学生";}
}class Teacher extends Person{public Teacher(){this.name="老师";}
}
- 哪些类型可以有Class对象
class :外部类,成员(成员内部类、静态内部类)、局部内部类、匿名内部类
interface :接口
[ ] : 数组
enum :枚举
annotation :注解@interface
primitive type : 基本数据类型
void
package com.axiaoleng1;import java.lang.annotation.ElementType;//所有类型的Class
public class Test06 {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; //voidClass c9 = Class.class; //ClassSystem.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);//只要元素类型与维度一样,就是同一个Classint[] a = new int[10];int[][] a1= new int[5][5];int[] b = new int[100];System.out.println(a1.getClass().hashCode());System.out.println(a.getClass().hashCode());System.out.println(b.getClass().hashCode());}
}
- Java内存分析


1、加载到内存,会产生一个类对应的Class对象
2、链接,链接结束后 m = 0
3、初始化
(){
System.out.println(“A类静态代码块初始化”);
m=300;
m=100;
}
package com.axiaoleng1;import jdk.internal.dynalink.beans.StaticClass;public class Test07 {public static void main(String[] args) {A a = new A();System.out.println(a.m);System.out.println(a.b);}
}class A {static {System.out.println("A类静态代码块初始化");m = 300;}static int m = 100;static int b = 200;static {System.out.println("A类静态代码块初始话2");b = 500;}public A(){System.out.println("A类的无参构造初始化");}
}

- 分析类的初始化

package com.axiaoleng1;public class Test08 {static{System.out.println("Main类被加载");}public static void main(String[] args) throws Exception{//Father m1 = new Father();//1、主动引用//Son m2 = new Son();//System.out.println(m1.b);//System.out.println(m2.m);//反射也会产生主动引用//Class.forName("com.axiaoleng1.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.axiaoleng1;public class Test09 {public static void main(String[] args) throws Exception {//获取系统类的加载器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.axiaoleng1.Test09").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"));}
}
双亲委派机制
- 获取类的运行时类的完整结构
package com.axiaoleng1;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class Test10 {public static void main(String[] args) throws Exception{Class c1 = Class.forName("com.axiaoleng1.User");//获得类的名字System.out.println(c1.getName()); //获得包名 + 类名System.out.println(c1.getSimpleName()); //获得类名//获得类的属性System.out.println("=============");Field[] fields = c1.getFields(); //只能找到public属性
// for(Field field : fields){
// System.out.println(field);
// }fields = c1.getDeclaredFields(); //找到全部的属性for(Field field : fields){System.out.println(field);}//获得指定属性的值// Field name=c1.getField("name");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();for(Constructor constructor : constructors){ //只能找到public构造器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);}
}
- 动态创建对象执行方法


- 两个重点
Object invoke(Object obj,Object … args)
1、Object对应原方法的返回值,若原方法无返回值,此时返回null
2、若原方法为静态方法,此时形参Object obj 可为null
3、若原方法形参列表为空,则Object[] args为null
4、若原方法声明为private,则需要在调用此 invoke()方法前,显示调用方法对象的setAccessible(true)方法,将可访问private的方法
setAccessible
1、Method和Field、Constructor对象都有setAccessible()方法
2、setAccessible作用是启动和禁用访问安全检查的开关
3、参数值为true则指示反射的对象在使用时应该取消JAVA语言访问检查
- 提高反射的效率,如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true
- 使得原本无法访问的私有成员也可以访问
参数值为false则指示反射的对象应该实施java语言访问检查
package com.axiaoleng1;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class Test11 {public static void main(String[] args) throws Exception{//获得Class对象Class c1 = Class.forName("com.axiaoleng1.User");//构造一个对象
// User user = (User)c1.newInstance(); //本质是调用了类的无参构造器
// System.out.println(user);//通过构造器创建对象
// Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
// User user1 = (User)constructor.newInstance("阿冷",001,20);
// System.out.println(user1);// 通过反射调用普通方法User user2 = (User) c1.newInstance();// 通过反射获取一个方法Method setName = c1.getDeclaredMethod("setName", String.class);//invoke : 激活的意思// (对象 ; "方法的值")setName.invoke(user2,"阿冷");System.out.println(user2.getName());//通过反射操作属性System.out.println("================");User user3 =(User)c1.newInstance();Field name = c1.getDeclaredField("name");//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessiblename.setAccessible(true);name.set(user3,"阿小冷");System.out.println(user3.getName());}
}
- 性能对比分析
package com.axiaoleng1;import java.lang.reflect.Method;public class Test12 {//普通方式调用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 Exception{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++){//user.getName();getName.invoke(user,null);}long endTime = System.currentTimeMillis();System.out.println("反射方法执行10亿次:"+(endTime-startTime)+"ms");}//反射方式调用 关闭检测public static void test03() throws Exception{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++){//user.getName();getName.invoke(user,null);}long endTime = System.currentTimeMillis();System.out.println("反射方法关闭检测执行10亿次:"+(endTime-startTime)+"ms");}public static void main(String[] args) throws Exception {test01();test02();test03();}
}
- 获取泛型信息

package com.axiaoleng1;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 Test13 {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 Exception {Method method = Test13.class.getMethod("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 = Test13.class.getMethod("test01",Map.class,List.class);Type genericReturnType = method.getGenericReturnType();if(genericReturnType instanceof ParameterizedType){ //Type[] actualTypeArguments = ((ParameterizedType) genericReturnType ).getActualTypeArguments();for (Type actualTypeArgument : actualTypeArguments) {System.out.println(actualTypeArgument);}}}}
- 反射操作注解

package com.axiaoleng1;import java.lang.annotation.*;
import java.lang.reflect.Field;public class Test14 {public static void main(String[] args) throws Exception{Class c1 = Class.forName("com.axiaoleng1.Student2");//通过反射获得注解Annotation[] annotations = c1.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}//获得注解的value的值Tableleng tableleng = (Tableleng) c1.getAnnotation(Tableleng.class);String value = tableleng.value();System.out.println(value);//获得类指定的注解Field f = c1.getDeclaredField("name");Fieldleng annotation = f.getAnnotation(Fieldleng.class);System.out.println(annotation.columnName());System.out.println(annotation.type());System.out.println(annotation.length());Field f1 = c1.getDeclaredField("id");Fieldleng annotation1 = f1.getAnnotation(Fieldleng.class);System.out.println(annotation1.columnName());System.out.println(annotation1.type());System.out.println(annotation1.length());Field f2 = c1.getDeclaredField("age");Fieldleng annotation2 = f2.getAnnotation(Fieldleng.class);System.out.println(annotation2.columnName());System.out.println(annotation2.type());System.out.println(annotation2.length());}
}@Tableleng("db_student")
class Student2{@Fieldleng(columnName = "db_id",type = "int",length = 10)private int id;@Fieldleng(columnName = "db_age",type = "int",length = 10)private int age;@Fieldleng(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;}@Overridepublic String toString() {return "Student2{" +"id=" + id +", age=" + age +", name='" + name + '\'' +'}';}
}//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Tableleng{String value();
}//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Fieldleng{String columnName();String type();int length();
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
