Java的注解是什么呢?
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
让我们来看看注解的基本使用
import java.lang.annotation.*;
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//表示我们的注解可以用在什么地方
@Retention(value = RetentionPolicy.RUNTIME)
//retention表示这个注解在什么地方可以被识别到.分别有三个级别,即source < class < runtime
@Documented
//表示我们的注解是否生成在JavaDOC当中
@Inherited
//代表子类可以继承父类的注解
public @interface MyAnnotation {
}
@MyAnnotation
class TestAnnotation {
@MyAnnotation
public void testMethod() {
}
}
以上演示了注解的基本自定义的一些属性设置及使用
那就再来自定义一个复杂一点的注解来试试看吧
import java.lang.annotation.*;
@MyAnnotation02(name = "zzh",school = {"CUIT"})
public class kuangAnnotation {
@MyAnnotation02(name = "zzh",school = {"CUIT"})
public static void main(String[] args) {
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation02 {
//注解的参数 : 参数类型 + 参数名()
String name() default "";
int age() default 0;
int id() default -1;
String[] school();
}
Java反射
Java反射是what?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为该语言语言的反射机制。
让我们来使用反射机制来创建几个对象耍耍
Class c1 = Class.forName("com.huazai.study.User");
System.out.println(c1.hashCode());
//通过包名来创建
Class c2 = testUser.getClass();
System.out.println(c2.hashCode());
//通过已有实例,使用getClass()来创建
Class<User> c3 = User.class;
System.out.println(c3.hashCode());
//知道类名,直接使用类名创建
Class<Integer> type = Integer.TYPE;
System.out.println(type.hashCode());
//内部类独有的通过TYPE来进行创建
//需要注意的是四个的hashcode都是相等的
获取类的各种结构
try {
A a = new A();
Class<? extends A> c1 = a.getClass();
//获取类名
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
System.out.println("==========================================");
//获得该类中全部的属性,getFields()只能找到public范围的属性
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获得指定的类中属性
Field declaredField = c1.getDeclaredField("m");
System.out.println(declaredField);
//获得本类及其父类的所有public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获得本类的所有方法
System.out.println("==========================================");
Method[] methods1 = c1.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
/**
* 获得指定的方法,需要注意的是private权限的方法是不能被获取到的
* 之所以需要getMethod的第二个parameterTypes参数
* 是因为有方法的重载,所以需要参数来确定具体的某个方法
*/
Method test2 = c1.getMethod("test2", String.class);
System.out.println(test2);
Method test = c1.getMethod("test",null);
System.out.println(test);
//获取指定的构造方法
System.out.println("==========================================");
Constructor<?>[] constructors = c1.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}//仅获得public方法
Constructor<?>[] constructors2 = c1.getDeclaredConstructors();
for (Constructor<?> constructor : constructors2) {
System.out.println(constructor);
}//获取所有方法
//同理,可以获得指定的构造器
} catch (Exception e) {
e.printStackTrace();
}
通过反射来对类的各个部分进行操作
try {
Class<?> c1 = Class.forName("com.huazai.study.User");
//构造一个对象,本质上会调用无参构造器
User lyt = (User) c1.getDeclaredConstructor().newInstance();
System.out.println(lyt);
//通过构造器创建对象
Constructor<?> constructor = c1.getDeclaredConstructor(int.class, String.class);
User zzh = (User) constructor.newInstance(18, "zzh");
System.out.println(zzh);
//通过反射来调用方法,使用invoke()来使用反射获取的方法
//假如说有一个需求是用字符串来调用对应的方法,就可以用反射来对应方法
User zzj = (User) c1.getDeclaredConstructor().newInstance();
Method test2 = c1.getDeclaredMethod("test2", String.class);
test2.invoke(zzj,"渣渣辉");
System.out.println("========================================================");
//通过反射来操作属性
User user4 = (User) c1.getDeclaredConstructor().newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
//不能直接操作私有属性,但是可以通过serAccessible()该方法可以让java去访问private权限的变量
name.set(user4,"另一个zzh");
System.out.println(user4.getName());
} catch (Exception e) {
e.printStackTrace();
}
普通方法和反射方法(开/关检测机制)的性能比较
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
}
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.printf("普通方法,This program had cost %d ms",endTime - startTime);
System.out.println();
}
public static void test02() throws Exception {
Class<?> c1 = Class.forName("com.huazai.study.User");
User user = (User) c1.getDeclaredConstructor().newInstance();
Method getName = c1.getMethod("getName");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user);
}
long endTime = System.currentTimeMillis();
System.out.printf("反射机制,This program had cost %d ms",endTime - startTime);
System.out.println();
}
public static void test03() throws Exception {
User preUser = new User();
Class<? extends User> c1 = preUser.getClass();
User user = (User) c1.getDeclaredConstructor().newInstance();
Method getName = c1.getMethod("getName");
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user);
}
long endTime = System.currentTimeMillis();
System.out.printf("反射机制(关闭安全性检查),This program had cost %d ms",endTime - startTime);
System.out.println();
}
运行结果:
普通方法,This program had cost 4 ms
反射机制,This program had cost 1712 ms
反射机制(关闭安全性检查),This program had cost 1066 ms