java注解和反射

注解不仅能给人看,还能给程序看(annotation)

可以被其他程序如编译器读取。

注解@override,@deprecated,@suppresswarnings等都是定义在java.lang包下面的,这三个就是内置注解。

@suppresswarnings(all)可以镇压全部警告。

===========================================================

元注解meta-annotation

是用来注解其他注解。

有四个:

@target  用于秒速注解的使用范围。

@retention  表示需要在什么级别保存该注释信息,描述注解的生命周期。source(源码)>class>runtime

@documented

@inherited

 

定义一个注解:

@Target(value = {ElementType.METHOD,ElementType.TYPE}) //表示我们的注解能用在哪些地方
@Retention(RetentionPolicy.RUNTIME) //表示注解在什么地方有效,在源码或者类或者在运行时
@Documented // 表示将我们的注解生成在javadoc中
@Inherited //表示子类可以继承父类的注解
@interface MyAnnotation{

}
====================================================================================
自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Test2 {
@MyAnnotation2(name = "bin")
public void test(){

}
@MyAnnotation3("")
public void test2(){

}

}


@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解的参数:参数类型+参数名();
String name()default ""; //default表示默认值
int age()default 0;
int id()default -1; //如果默认值为-1,代表不存在
String[] schools()default {"清华","北大"};
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{

String value(); //如果只有一个值,最好用value命名,这个值可以省略

}
===============================================================================
反射
用反射获得class类

public class Test4 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这"+person.name);
//通过对象获得class类
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//forname获得
Class c2 = Class.forName("annotation.Student");
System.out.println(c2.hashCode());
//通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());

//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5.hashCode());


}

}
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="老师";
}

}

==================================================================

有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;//
Class c9 =Class.class;//
=============================================
只要元素类型和维度一样,就是同一个Class
=============================================
通过子类调用父类的静态变量,子类不会被加载。
定义数组不会加载类。
调用类中的常量,类不会被加载。
只有在new出一个对象,或者通过反射得到一个类时,这个类才会初始化
=======================================================
引导类加载器(C++编写),扩展类加载器,系统类加载器。

public class Test8 {
public static void main(String[] args) throws ClassNotFoundException {
//获得系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);

//获得系统类加载器的父类加载器:扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);

//获得扩展类加载器的父类加载器:根加载器,这个java直接的得不到的
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);

//测试当前类的加载器
ClassLoader classLoader = Class.forName("annotation.Test8").getClassLoader();
System.out.println(classLoader);

classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);

//获得加载器的加载路径
System.out.println(System.getProperty("java.class.path"));

//双亲委派机制:如果你自己写的包的路径跟java已经有的包路径一样,你自己写的就不会被加载。
}
}

========================================================================================
通过反射得到类的属性和方法:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test9 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("annotation.User");
//获得类的名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//获得类的属性
Field[] field = c1.getFields();//只能找到public属性
for (Field field1 : field) {
System.out.println(field1);

}

field=c1.getDeclaredFields();//可以找到所有属性
for (Field field2 : field) {
System.out.println(field2);

}

//获得指定属性
Field name = c1.getDeclaredField("name");
System.out.println(name);

//获得类的方法
Method[] methods = c1.getMethods();//获得本来和父类的所有public方法
for (Method method : methods) {
System.out.println(method);

}

methods=c1.getDeclaredMethods();//获得本来的所有方法
for (Method method : methods) {
System.out.println(method);
}

//获得指定方法
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);

//获得指定的构造器
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);

}
}

===================================================================================================
通过反射动态创建对象,操作属性和方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = Class.forName("annotation.User");

//构造一个对象
User user = (User) c1.newInstance();//本质是调用类的无参构造器
System.out.println(user);


//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 =(User) constructor.newInstance("wang", 001, 18);
System.out.println(user2);

//通过反射调用方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3,"wang"); //invoke是激活的意思
System.out.println(user3.getName());

//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);//把程序的安全监测关闭,可以操作private属性
name.set(user4,"tian");
System.out.println(user4.getName());


}
}

================================================================================
三种方式的性能检测:一个是普通的直接new一个对象,第二是用反射创建对象,第三个是用反射创建对线个并且关闭安全监测。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test11 {
public static void test01(){
User user = new User();
long start = System.currentTimeMillis();

for (int i = 0; i < 1000000000; i++) {
user.getName();

}
long end = System.currentTimeMillis();
System.out.println(end-start+"ms");
}

public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);

long start = System.currentTimeMillis();

for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);

}
long end = System.currentTimeMillis();
System.out.println(end-start+"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 start = System.currentTimeMillis();

for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);

}
long end = System.currentTimeMillis();
System.out.println(end-start+"ms");
}

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test01();
test02();
test03();
}


}

得到的结果是:

4ms
2686ms
1378ms

结论:性能相处巨大。

=====================================================================

通过反射获得注解信息

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("annotation.Student2");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);

//获得注解的value值
Table annotation1 = (Table) c1.getAnnotation(Table.class);
String value = annotation1.value();
System.out.println(value);

//获得类指定的注解
Field f = c1.getDeclaredField("name");
FieldWang f1 = f.getAnnotation(FieldWang.class);
System.out.println(f1.columnName());
System.out.println(f1.length());
System.out.println(f1.type());

}
}
}
@Table("student")
class Student2{
@FieldWang(columnName = "id",type = "varchar",length = 10)
private String name;
@FieldWang(columnName = "id",type = "int",length = 10)
private int age;
@FieldWang(columnName = "id",type = "int",length = 10)
private int id;

public Student2() {
}

public Student2(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 +
'}';
}
}


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldWang{
String columnName();
String type();
int length();

}

 

posted @ 2021-03-06 19:52  即墨非音  阅读(55)  评论(0)    收藏  举报