JAVA注解和反射
- 一:注解
- 二:反射
- 1.反射概述:
- 2.初识类加载内存机制:
- 3.初识类加载器:
- 4.反射获取泛型信息:
- 5.反射调用注解:
一:注解
1.注解格式:@“注解名“
2.内置注解:@Override,@Deprecated,@SuppressWarnings
3.元注解: @Target,@Retention(RUNTIME>CLASS>SOURCE),@document,@Inherited
4.自定义注解:a.@interface自动继承了Annotation接口了
b.注解参数:参数类型+参数名()
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Main {
@MyAnnatation01(name="张三")
public void func01(){
System.out.println();
}
@MyAnnatation02("张三")
public void func02(){
System.out.println();
}
@MyAnnatation03(age=22)
public void func03(){
System.out.println();
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation01{
//注解参数:参数类型+参数名()
String name();
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation02{
String value(); //可用默认
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnatation03{
String name() default "";
int id()default -1;
int[] score()default {85,75,60};
int age();
}
二:反射
1.反射概述:
1.java是静态语言,通过反射变为了准动态语言
2.反射很强大,可以通过Refletion API任何类的内部信息,并能操作任意对象的内部属性及方法
3.四种获取Class对象方式(类名):
(1. forname(“包名下的路径”)
(2. 对象名.getClass()
(3. 类名.class
(4. 基本类型包装类.Type
5.一种获取其父类的Class对象方式: 对象名.getSuperClass()
6.类被加载后,其该类的整体结构被封装到Class对象中,在内存中,一个类只有一个Class对象
package reflection;
import java.lang.annotation.ElementType;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Person user = new Person();
//1.通过forName("")获取
Class c1 = Class.forName("reflection.Person");
Class c2 = Class.forName("reflection.Person");
System.out.println("c2 = " + c2);
//2.通过对象获取
Man man = new Man();
Class c3 = man.getClass();
System.out.println("c3 = " + c3);
//3.通过类名获取
Class c4 = Person.class;
System.out.println("c4 = " + c4);
Class c5 = Man.class;
System.out.println("c5 = " + c5);
Class c6 = Main.class;
System.out.println("c6 = " + c6);
//4.通过基本类型包装类的Type属性
Class c7 = Integer.TYPE;
System.out.println("c7 = " + c7);
//5.获取父类的Class名
System.out.println("c8 = " + c3.getSuperclass());
//6.类被加载后,其该类的整体结构被封装到Class对象中,在内存中,一个类只有一个Class对象
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c6.hashCode());
System.out.println("-------------");
showAllClass();
}
//7.大部分类型的Class对象
public static void showAllClass(){
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = int[].class;
Class c4 = int[][].class;
Class c5 = Override.class;
Class c6 = ElementType.class;
Class c7 = Integer.class;
Class c8 = Void.class;
Class c9 = 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);
System.out.println("-----------");
//同类型的数组其Class对象与数组的长度无光
int[] a1 =new int[10];
int[] a2=new int[100];
System.out.println(a1.getClass());
System.out.println(a2.getClass());
}
}
class Person {
String name;
int age;
public int id;
public Person(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
public Person() {
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", age=" + age +
", id=" + id +
'}';
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setId(int id) {
this.id = id;
}
private void test(){}
}
class Man extends Person{
}
2.初识类加载内存机制:
1.类加载:将Class字节码文件加载到内存中,对应生成唯一的Class对象(方法区——>堆)
2.链接:为所有类变量(static)分配内存并为其设置默认初始值(方法区)
3.初始化:()将所有赋值动作和静态代码块合并(栈)
package reflection;
public class ClassLoading01 {
static{
System.out.println("Main被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
ClassMemory(); //类加载内存机制
//1.通过new来主动引用
Son son=new Son();
//2.通过forName()来主动引用
//Class aClass = Class.forName("reflection.Son");
//1.子类调用父类的静态方法不会触发自身类的主动引用
//System.out.println(Son.mFather);
//2.创建数组不会触发主动引用
//Son[] vsSon=new Son[10];
}
//类内存加载机制
public static void ClassMemory(){
A a=new A(); //new操作在堆区
System.out.println(a.m);
}
}
//测试类加载的内存机制
class A{
static{
System.out.println("静态代码块初始化");
m=300;
}
public static int m=100;
A(){
System.out.println("A的构造函数调用");
}
}
class Father{
static {
System.out.println("父类被加载");
}
public static int mFather=1;
}
class Son extends Father{
static {
System.out.println("子类被加载");
}
public static int mSon=1;
public static final int nFinalSon=2;
}
3.初识类加载器:
一.类加载器:
1.系统类加载器:ClassLoader.getSystemClassLoader()
2.扩展类加载器:systemClassLoader.getParent()
3.引导类(根)加载器(C/C++编写):扩展类加载器.getParent()
4.测试当前类和内置类的加载器
5.获取系统加载器可以加载的路径:同4获取class对象.getClassLoader()
6.双亲委派机制
二.获取类运行时结构:
1.获取类名(全包名,只类名):Class对象.getName()
2.获取属性值(公有,所有,指定):
公有: Class对象.getFields()
所有:Class对象.getDeclaredFields()
指定:对应方法去掉s+属性名参数
3.获取方法(公有,所有,指定):
公有:Class对象.getMethods()
所有:Class对象.getDeclaredMethods()
指定:对应方法去掉s+函数名参数
4.获取构造方法(公有,指定)
公有:Class对象.getConstructors()
指定:对应函数去掉s+实际参数的class
三:反射动态创建对象并执行方法:
1.无参创建对象和有参创建:
无参:Class对象.newInstance()
有参:Class对象..getConstructor(实际参数的Class对象)
2.获取方法并调用:
获取:Class对象.getMethod("方法名", 参数的Class对象)
调用:方法名.invoke(创建的对象名, 参数)
3.操作属性并调用
权限检测:创建的对象名.setAccessible(true),ture为关闭
调用:获取属性名后.set(创建的对象名,参数)
四:对象调用性能对比分析:
1.普通对象调用(约3ms)
2.通过反射调用(约3592ms)
3.通过反射调用并关掉安全性权限检测(约1847ms)
4.若频繁调用反射,可关闭安全检测提升性能
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ClassLoading02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//一:类加载器
classLoadTest();
//二:获取类运行时结构
getClassRuning();
//三:反射动态创建对象并执行
createClassRuning();
//四:对象调用性能分析
performanceAnalyze();
}
//一:类加载器
public static void classLoadTest() throws ClassNotFoundException {
//获取系统加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取扩展类加载器
ClassLoader parent1 = systemClassLoader.getParent();
System.out.println(parent1);
//获取根加载器(无法直接获取)
ClassLoader parent2 = parent1.getParent();
System.out.println(parent2);
//获取当前类的加载器
Class> aClass = Class.forName("reflection.ClassLoading02");
System.out.println(aClass.getClassLoader());
//获取内置类的加载器:Object类的加载器是根加载器
ClassLoader classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
//获取系统加载器可加载的路径
System.out.println(System.getProperty("java.class.path"));
}
//二:获取类运行时结构
public static void getClassRuning() throws NoSuchFieldException, NoSuchMethodException {
System.out.println("----------------");
Person person = new Person();
Class extends Person> aClass = person.getClass();
//1.获取类名
String name = aClass.getName();
String simpleName = aClass.getSimpleName();
System.out.println("全名:" + name);
System.out.println("类名" + simpleName);
System.out.println("----------------");
//2.获取属性值
Field[] declaredFields = aClass.getDeclaredFields();
Field[] fields = aClass.getFields();
Field field = aClass.getDeclaredField("name");
Field id = aClass.getField("id");
for (Field declaredField : declaredFields) {
System.out.println("所有属性:"+declaredField);
}
for (Field field1 : fields) {
System.out.println("公有属性:"+field);
}
System.out.println("指定私有属性:" + field);
System.out.println("指定共有属性:"+id);
System.out.println("----------------------");
//3.获取方法
Method[] methods = aClass.getMethods();
Method[] declaredMethods = aClass.getDeclaredMethods();
Method getId = aClass.getMethod("setId", int.class);//重载,第二个参数是方法的参数类型
Method test = aClass.getDeclaredMethod("test", null);
for (Method method : methods) {
System.out.println("共有方法:"+method);
}
for (Method declaredMethod : declaredMethods) {
System.out.println("所有方法:"+declaredMethod);
}
System.out.println("指定共有方法:" + getId);
System.out.println("指定私有方法:"+test);
System.out.println("-------------------");
//4.获取构造器
Constructor>[] constructors = aClass.getConstructors();
for (Constructor> constructor : constructors) {
System.out.println("获取构造器:"+constructor);
}
Constructor extends Person> constructor = aClass.getConstructor(String.class, int.class, int.class);
System.out.println("获取指定构造器:"+constructor);
}
//三:反射动态创建对象并执行
public static void createClassRuning() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
System.out.println("###################");
Class> aClass = Class.forName("reflection.Person");
//1.获取无参对象
Object o = aClass.newInstance();
System.out.println("反射创建无参对象:"+o);
//2.获取有参对象
Constructor> constructor = aClass.getConstructor(String.class, int.class, int.class);
Object person = constructor.newInstance("张三", 22, 101);
System.out.println("反射创建有参对象:"+person);
//3.获取方法
Method setName = aClass.getMethod("setName", String.class);
setName.invoke(person, "李四");//invoke激活函数
System.out.println("反射调用函数:"+person);
//4.操作属性
Field personName = aClass.getDeclaredField("name");
//关闭安全权限检测
personName.setAccessible(true);
personName.set(person,"王五");
System.out.println("反射操作属性:name:"+personName.get(person));
}
//四:对象调用性能分析
public static void performanceAnalyze() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
System.out.println();
System.out.println("---------------------");
test01();//3ms
test02();//3592ms
test03();//1847ms
}
public static void test01(){
Person person=new Person("zhangsan",18,28);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
person.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通对象调用:"+(endTime-startTime)+"ms");
}
public static void test02() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class aClass = Class.forName("reflection.Person");
Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
Object person = constructor.newInstance("zhangsan", 18, 28);
Method getName = aClass.getMethod("getName", null);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(person,null);
}
long endTime = System.currentTimeMillis();
System.out.println("通过反射调用:"+(endTime-startTime)+"ms");
}
public static void test03() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class aClass = Class.forName("reflection.Person");
Constructor constructor = aClass.getConstructor(String.class, int.class, int.class);
Object person = constructor.newInstance("zhangsan", 18, 28);
Method getName = aClass.getMethod("getName", null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(person,null);
}
long endTime = System.currentTimeMillis();
System.out.println("通过反射并关闭安全检测调用:"+(endTime-startTime)+"ms");
}
}
4.反射获取泛型信息:
1.获取函数的泛型参数类型:
泛型参数类型:方法名.getGenericParameterTypes()
判断泛型参数为参数化类型:if(genericParameterType instanceof ParameterizedType)
强转为参数化类型:((ParameterizedType) genericParameterType).getActualTypeArguments()
2.获取函数的返回泛型类型:
返回泛型类型:方法名.getGenericReturnType()
判断泛型参数为参数化类型:同上
强转为参数化类型:同上
在这里插入代码片package reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class GetGenericityInformantion {
public void test01(Map arg){
}
public Map test02(){
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
//1.获取函数的泛型参数类型
Method test01 = GetGenericityInformantion.class.getMethod("test01", Map.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);
}
}
}
System.out.println("-------------------");
//2.获取函数的返回泛型类型
Method test02 = GetGenericityInformantion.class.getMethod("test02");
Type genericReturnType = test02.getGenericReturnType();
System.out.println("函数返回的泛型类型:"+genericReturnType);
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("函数返回的泛型信息:"+actualTypeArgument);
}
}
}
}
5.反射调用注解:
1.反射调用类的注解的value
2.反射调用类属性的注解value
package reflection;
import com.sun.jdi.Value;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class ReflectionCallAnnotation {
public static void main(String[] args) throws ClassNotFoundException {
//1.获取类的注解信息
Class> c1 = Class.forName("reflection.Student");
Annotation[] annotations = c1.getAnnotations();//直接通过Class对象获取注解
for (Annotation annotation : annotations) {
System.out.println("获取类注解信息:"+annotation);
}
//2.获取类注解的value()
ClassAnnotation annotation = (ClassAnnotation)c1.getAnnotation(ClassAnnotation.class);
System.out.println("获取类注解的value():"+annotation.value());//传递注解class参数获取
//2.获取类属性的注解信息
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {//传递注解class参数获取
FieldAnnotation annotation1 = declaredField.getAnnotation(FieldAnnotation.class);
System.out.println("获取类属性的直接信息:"+"<"+declaredField.getName()+">"+annotation1.name()+" "+annotation1.type()+" "+annotation1.length());
}
}
}
@ClassAnnotation("db_student")
class Student{
@FieldAnnotation(name="sName",type ="varchar",length = 5)
private String sName;
@FieldAnnotation(name="nIage",type = "int",length = 6)
private int nIge;
@FieldAnnotation(name = "sId",type = "varchar",length = 12)
private String sId;
public Student() {
}
public Student(String sName, int nIge, String sId) {
this.sName = sName;
this.nIge = nIge;
this.sId = sId;
}
@Override
public String toString() {
return "Student{" +
"sName='" + sName + ''' +
", nIge=" + nIge +
", sId='" + sId + ''' +
'}';
}
public void setsName(String sName) {
this.sName = sName;
}
public void setnIge(int nIge) {
this.nIge = nIge;
}
public void setsId(String sId) {
this.sId = sId;
}
public String getsName() {
return sName;
}
public int getnIge() {
return nIge;
}
public String getsId() {
return sId;
}
}
//对类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ClassAnnotation{
String value();
}
//对属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldAnnotation{
String name();
String type();
int length();
}