Java 注解和反射 学习笔记(2021.10.19)
注解和反射
目录
一、什么是注解
注解(Annotation)作用:可以被其他驱动读取;对代码做出解释(这一点和注释没有区别)
注解结构:以@开头
注解在哪里使用:方法、类、字段、包等地方使用
例子:如
public class Demo01 extends Object {
public static void main(String[] args) {
}
@Override
public String toString() {
return super.toString();
}
}
二、内置注解
- @Deprecated:不推荐使用,可能有危险或者更好的选择
- @SuppressWornings:镇压警告,把警告变成正常
三、元注解
元注解负责注解其他注解,有四个:
- @Target:用于描述注解的使用范围(即:别描述的注解可以用在什么地方
- @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
- (SOURCE<CLASS<RUNTIME)
- @Documented:是否这个注解在生成文档上生成
- @Inherited:表示这个注解是否能被继承
Demo:
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation{
}
四、自定义注解
package com.xiaowei9s.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Demo03 {
@MyAnnotation1(name = "xiaowei",id = 15)
public void test(){}
@MyAnnotation2()
public void test1(){}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation1{
String name();
int age() default 18;//有默认值的情况下在使用注解的时候可以不必要输入值
int id();
String[] hobby() default {"打乒乓球","打篮球"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
String name() default "";
int age() default 18;//有默认值的情况下在使用注解的时候可以不必要输入值
int id() default -1;
String[] hobby() default {"打乒乓球","打篮球"};
}
五、反射概述
动态语言:JavaScript,动态语言可以在运行的时候可以改变自身结构的。
静态语言:C/C++,Java(准动态,利用反射机制,却有些不安全)

优点:
实现动态创建对象和编译,灵活性强
缺点:
对性能有影响,因为是解释操作
六、获得反射对象
package com.xiaowei9s.reflection;
//什么叫反射
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.xiaowei9s.reflection.User");
Class c2 = Class.forName("com.xiaowei9s.reflection.User");
Class c3 = Class.forName("com.xiaowei9s.reflection.User");
Class c4 = Class.forName("com.xiaowei9s.reflection.User");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
class User{
public User(String name, int age) {
this.name = name;
this.age = age;
}
String name;
int age;
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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
七、得到Class类的几种方式


获取Class实例:
package com.xiaowei9s.reflection;
//如何获得Class类的实例
public class Demo02 {
public static void main(String[] args) throws ClassNotFoundException {
Student stu = new Student();
//方式一,变量名.getClass()
Class c1 = stu.getClass();
System.out.println(c1.hashCode());
//方式二,类名.class
Class c2 = Student.class;
System.out.println(c2.hashCode());
//方式三,forName()
Class c3 = Class.forName("com.xiaowei9s.reflection.Student");
System.out.println(c3.hashCode());
//方式四,只有包装类有,TYPE
Class c4 = Integer.TYPE;
System.out.println(c4.hashCode()+" "+c4);
//获取类的结构
System.out.println(c1.getName());
System.out.println(c1.getDeclaredFields());
System.out.println(c1.getSuperclass());
}
}
class Person{
public String name;
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
八、所有类型的Class对象
- 类
- 接口
- 数组
- 枚举
- 注解
- 基本数据类型
- void
package com.xiaowei9s.reflection;
import java.lang.annotation.ElementType;
public class Demo03 {
public static void main(String[] args) {
Class c1 = String.class;
Class c2 = Runnable.class;
Class c3 = Override.class;
Class c4 = String[].class;
Class c5 = String[][].class;
Class c6 = ElementType.class;
Class c7 = void.class;
Class c8 = Class.class;
Class c9 = int.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);
//只要类型一致,就是同一个hashCode,获得同一个Class类
int[] ints = new int[100];
int[] ints1 = new int[10];
System.out.println(ints.getClass().hashCode());
System.out.println(ints1.getClass().hashCode());
}
}
九、类加载内存分析
类加载器理解:

package com.xiaowei9s.reflection;
public class Demo04 {
public static void main(String[] args) {
System.out.println("main方法");
A a = new A();
System.out.println(a.m);//m = 100
/*
1. 在静态方法区内存中加载Demo04类的静态变量方法等。。
2. 在静态方法区内存中加载A类的静态方法区中的变量。
3. 在堆中分别建立Demo04、A类的Class对象。
4. 初始化:
<clinit>(){//合并静态代码
System.out.println("静态代码");
m = 300;
m = 100;
}
5. 执行main方法
*/
}
}
class A{
static {
System.out.println("静态代码");
m = 300;
}
static int m = 100;
public A(){
System.out.println("构造代码");
}
}
十、分析类初始化

package com.xiaowei9s.reflection;
import java.sql.SQLOutput;
public class Demo05 {
static {
System.out.println("Main被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
//主动引用
//Son son = new Son();
//反射加载类
//Class.forName("com.xiaowei9s.reflection.Son");
//数组使用
Son[] sons = new Son[10];
//访问常量
System.out.println(Son.M);
//访问静态变量
System.out.println(Son.i);
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
}
}
class Father{
static int i = 10;
static {
System.out.println("父类被加载");
i = 20;
}
static final int M = 5;
}
十一、类加载器

package com.xiaowei9s.reflection;
public class Demo06 {
public static void main(String[] args) {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统加载类的父类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取拓展加载类的父类加载器-->根加载器,使用(C/C++)编写,无法查询到
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是哪个加载器加载的
ClassLoader classLoader = Demo06.class.getClassLoader();
System.out.println(classLoader);
//测试JDK内置类是哪个类加载的
ClassLoader classLoader1 = Object.class.getClassLoader();
System.out.println(classLoader1);
//如何获得系统类加载器可加载的路径
System.out.println(System.getProperty("java.class.path"));
}
}
十二、获取类的运行结构

package com.xiaowei9s.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo07 {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
Class c1 = User.class;
//获得类的属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
declaredFields = c1.getFields();//只有public,方法和构造方法同理
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Field name = c1.getDeclaredField("name");//获得指定的字段
System.out.println(name);
//获得类的方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
Method setName = c1.getDeclaredMethod("setName", String.class);
System.out.println(setName);//获得指定方法
//获得类构造器
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获得指定构造器方法同上
}
}
十三、动态创建对象执行方法
package com.xiaowei9s.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo08 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1 = User.class;
//通过反射创建对象
//User u = (User) c1.newInstance();//如果没有空构造器则不能使用这个方法构造对象
//System.out.println(u);
//通过获取构造器创建对象
Constructor constructor = c1.getConstructor(String.class, int.class);
User u = (User) constructor.newInstance("xiaowei", 18);
System.out.println(u);
//通过反射获取方法
Method getName = c1.getDeclaredMethod("getName");
System.out.println(getName.invoke(u));//invoke是激活的意思
//通过反射来操纵属性
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(u,"xiaowei9s");//私有无法直接操纵
System.out.println(getName.invoke(u));
}
}
十四、性能对比分析
package com.xiaowei9s.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
public class Demo09 {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
test01();
test02();
test03();
}
//普通方法
private static void test03() {
User user = new User("1", 1);
long stime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long etime = System.currentTimeMillis();
System.out.println("普通方法访问10亿次用时"+(etime-stime)+"ms");
}
//反射方法
private static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
User user = new User("1", 1);
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName");
long stime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user);
}
long etime = System.currentTimeMillis();
System.out.println("反射方法访问10亿次用时"+(etime-stime)+"ms");
}
//关闭检测
private static void test01() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
User user = new User("1", 1);
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName");
getName.setAccessible(true);
long stime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user);
}
long etime = System.currentTimeMillis();
System.out.println("关闭检测访问10亿次用时"+(etime-stime)+"ms");
}
}
十五、获取泛型信息
package com.xiaowei9s.reflection;
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 Demo10 {
public Map<String,User> test01(Map<String,User> map){
return null;
}
public Map<String,User> test02(List<String> list,Map<String,User> map){
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Class<Demo10> c1 = Demo10.class;
//获取方法内参数的泛型
Method test01 = c1.getDeclaredMethod("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);
}
}
}
Method test02 = c1.getDeclaredMethod("test02", List.class, Map.class);
Type genericParameterTypes1 = test02.getGenericReturnType();
if (genericParameterTypes1 instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterTypes1).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
十六、获取注解信息
package com.xiaowei9s.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Demo11 {
public static void main(String[] args) throws NoSuchFieldException {
Class c1 = Student1.class;
TableWei annotation = (TableWei) c1.getAnnotation(TableWei.class);
System.out.println(annotation.value());
Field name = c1.getDeclaredField("name");
Annotation[] annotations =name.getAnnotations();
for (Annotation fieldWei : annotations) {
FieldWei f = (FieldWei) fieldWei;
System.out.println(f.colName());
System.out.println(f.length());
System.out.println(f.type());
}
}
}
@TableWei("db_stu")
class Student1{
@FieldWei(colName = "id",type = "int",length = 10)
private int id;
@FieldWei(colName = "age",type = "int",length = 3)
private int age;
@FieldWei(colName = "name",type = "String",length = 10)
private String 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;
}
public Student1(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableWei{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldWei{
String colName();
String type();
int length();
}
知识来源:kuangstudy.com
慢慢来慢慢来

浙公网安备 33010602011771号