注解与反射

注解和反射

内置注解

  • @Override 重写的注释

  • @Deprecatde 不推荐使用,,但是可以使用,或者有更好的方式

  • @SuppressWarnings 用来抑制编译时的警告信息与前两个注释不同,你需要添加一个参数才能正确使用,这些参数已经是定义好的,

  1. "all"

  2. "unchecked"

  3. "uncheched",deprecation"

  4. 等等

  5. package demo04;
    @SuppressWarnings("all")
    public class Test01 {
       @Deprecated
       public static void add() {
           System.out.println("过时的方法");
      }

       @Override
       public String toString() {
           return super.toString();
      }

       public static void main(String[] args) {
          add();
      }
    }

元注解

  • @Target 表示我们的注解可以用在哪些地方

  • @Retention 表示在源码还是类或者是运行时

    package demo04;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    @MyCloud
    public class Test02 {

    }

    @Target(value = ElementType.TYPE)
    @Retention(value = RetentionPolicy.RUNTIME)
    @interface MyCloud {

    }

自定义注解

package demo04;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@MyAnnotition("")
public class Test03 {
   @MyAnnotition("")
   public void test(){
       
  }
   @MyAnnotition1(name = "小白",age=24)
   public void test1(){
       
  }
   
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotition{
   //注解参数   参数类型+参数名();
   //如果参数只有一个的话直接可以写成value
   String value();
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface  MyAnnotition1{
   //如果为多个参数需要些具体的参数名了
   String name();
   int age() ;
   String hobby() default "";
}

反射

  • Java Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得 任何类的内部信息,,并能直接操作任意对象的内部属性及方法。

  • 正常方式:引入需要的“包”名称--->通过new实例化--->取得实例化对象

  • 反射方式:实例化独享--->getClass()方法--->得到完整的“包类”名称

  • 优点: 可以实现动态的创建对象和编译,,体现出很大的灵活性

  • 缺点:对性能有影响,使用反射基本上是一种解释操作,我们可以告诉JVM,,我们希望做什么并且满足我们的要求这类操作总是慢于直接执行相同的操作

获得反射对象

package demo04;
public class Test04 {
   public static void main(String[] args) throws ClassNotFoundException {

       Class<?> aClass = Class.forName("demo04.User");
       Class<?> aClass1 = Class.forName("demo04.User");
       Class<?> aClass2 = Class.forName("demo04.User");
       Class<?> aClass3 = Class.forName("demo04.User");
       System.out.println(aClass.hashCode());
       System.out.println(aClass1.hashCode());
       System.out.println(aClass2.hashCode());
       System.out.println(aClass3.hashCode());
  }
}
class User{
   int age;
   String name;
   int id;

   public User() {
  }

   public User(int age, String name, int id) {
       this.age = age;
       this.name = name;
       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 int getId() {
       return id;
  }

   public void setId(int id) {
       this.id = id;
  }

   @Override
   public String toString() {
       return "User{" + "age=" + age + ", name='" + name + '\'' + ", id=" + id + '}';
  }
}

得到Class类的几种方式

package demo05;

public class Testclass {
   public static void main(String[] args) throws ClassNotFoundException {
       //创建对象
       Person person = new Student();
       Class c1 = person.getClass();
       System.out.println(person.name = "小王");
       System.out.println(c1.hashCode());
       System.out.println("======================");
       //Class.forname()获得
       Class c2 = Class.forName("demo05.Student");
       System.out.println(c2.hashCode());
       System.out.println("=====================");
       //通过类名.class访问
       Class<Student> c3 = Student.class;
       System.out.println(c3.hashCode());
       System.out.println("====================");
       //基本内置类型都有一个包装类,包装类都有一个TYPE属性
       Class<Integer> c4 = Integer.TYPE;
       System.out.println(c4);
       System.out.println("=====================");
       //获得父类类型
       Class c5 = c1.getSuperclass();
       System.out.println(c5);

  }
}

class Person {
   String name;

   public Person() {
  }

   public Person(String name) {
       this.name = name;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }

   @Override
   public String toString() {
       return "Person{" +
               "name='" + name + '\'' +
               '}';
  }
}

class Student extends Person {

}

class Teacher extends Person {

}

所有类型的class对象

package demo05;

import java.lang.annotation.ElementType;

public class Test01 {
   public static void main(String[] args) {
       Class c1 = Class.class;
       System.out.println(c1);
       Class c2 = Override.class;
       System.out.println(c2);
       Class c3 = String[].class;
       System.out.println(c3);
       Class c4 = int[][].class;
       System.out.println(c4);
       Class c5= void.class;
       System.out.println(c5);
       Class c6= ElementType.class;
       System.out.println(c6);
       Class c7 = int.class;
       Class c8 = Integer.class;
       Class c9 = Comparable.class;
       System.out.println(c7);
       System.out.println(c8);
       System.out.println(c9);
  }
}

获取类的运行时的结构

package demo06;

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

//获取类的信息
public class Test01 {
   public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
       Class c1 = Class.forName("demo06.UserBean");
     /* Class<UserBean> userBeanClass = UserBean.class;
       System.out.println(userBeanClass.getName());*/
       //获得完整类的名字
       System.out.println(c1.getName());
       //获得简单的类名字
       System.out.println(c1.getSimpleName());
       System.out.println("==========================");
       //获得类的属性
       //只能获得共有属性
       Field[] fields = c1.getFields();
       for (Field field : fields) {
           System.out.println(field);
      }
       System.out.println("==============================");
       //所有属性都能获得
       Field[] declaredFields = c1.getDeclaredFields();
       for (Field declaredField : declaredFields) {
           System.out.println(declaredField);
      }
       System.out.println("============================");
       //获取指定共有属性(如果获得属性时非public,会报异常)
       Field field1 = c1.getField("sex"); //会报异常,因为sex公共的
       System.out.println(field1);
      /* Field field = c1.getField("hobby"); //会报异常,因为name是私有的
       System.out.println(field);*/
       System.out.println("============================");
       //获得指定所有类型属性
       System.out.println(c1.getDeclaredField("name"));
       System.out.println("============================");
       //只能获得指定的public方法
       Method method = c1.getMethod("getName",null);
       System.out.println(method);
       System.out.println("======================================");
       //指定所有类型方法都能获得
       Method declaredMethod = c1.getDeclaredMethod("getHobby",null);
       System.out.println(declaredMethod);
       System.out.println("===========================================");
       //获得所有public的方法,获得本类以及父类所有的public方法
       Method[] methods = c1.getMethods();
       for (Method method1 : methods) {
           System.out.println(method1);
      }
       System.out.println("================================");
       //获得所有的的本类所有类型的方法,不能获取父类的方法
       Method[] declaredMethods = c1.getDeclaredMethods();
       for (Method declaredMethod1 : declaredMethods) {
           System.out.println(declaredMethod1);
      }
  }
}

class UserBean {
   public String sex;
   private String name;
   private int id;
   private int age;
   private String hobby;

   public UserBean() {
  }

   public UserBean(String name, int id, int age, String hobby) {
       this.name = name;
       this.id = id;
       this.age = age;
       this.hobby = hobby;
  }

   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;
  }

   public String getHobby() {
       return hobby;
  }

   public void setHobby(String hobby) {
       this.hobby = hobby;
  }

   @Override
   public String toString() {
       return "UserBean{" +
               "name='" + name + '\'' +
               ", id=" + id +
               ", age=" + age +
               ", hobby='" + hobby + '\'' +
               '}';
  }
   private void add(){
       System.out.println("nihao");
  }
}

//运行结果
D:\Environment\jdk\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA
   
   
demo06.UserBean
UserBean
==========================
public java.lang.String demo06.UserBean.sex
==============================
public java.lang.String demo06.UserBean.sex
private java.lang.String demo06.UserBean.name
private int demo06.UserBean.id
private int demo06.UserBean.age
private java.lang.String demo06.UserBean.hobby
============================
public java.lang.String demo06.UserBean.sex
============================
private java.lang.String demo06.UserBean.name
============================
public java.lang.String demo06.UserBean.getName()
======================================
public java.lang.String demo06.UserBean.getHobby()
===========================================
public java.lang.String demo06.UserBean.toString()
public java.lang.String demo06.UserBean.getName()
public int demo06.UserBean.getId()
public void demo06.UserBean.setName(java.lang.String)
public void demo06.UserBean.setAge(int)
public java.lang.String demo06.UserBean.getHobby()
public void demo06.UserBean.setId(int)
public void demo06.UserBean.setHobby(java.lang.String)
public int demo06.UserBean.getAge()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
================================
private void demo06.UserBean.add()
public java.lang.String demo06.UserBean.toString()
public java.lang.String demo06.UserBean.getName()
public int demo06.UserBean.getId()
public void demo06.UserBean.setName(java.lang.String)
public void demo06.UserBean.setAge(int)
public java.lang.String demo06.UserBean.getHobby()
public void demo06.UserBean.setId(int)
public void demo06.UserBean.setHobby(java.lang.String)
public int demo06.UserBean.getAge()

Process finished with exit code 0

 

Java内存分析

  • Java内存中包含堆、栈、方法区

  • 堆中存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用

  • 栈中存放基本数据类型(包含这个基本数据类型的具体数值),引用对象的变量(会存放这个引用在堆里的具体地址)

  • 方法区可以被所有线程共享,包含了class和static变量

动态创建对象执行方法

package demo06;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

//通过反射,动态的创建对象
public class Test04 {
   public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
       //获取类
       Class c1 = Class.forName("demo06.UserBean");
       //构建对象
       /*UserBean userBean = (UserBean) c1.newInstance();//本质调用了无参构造器
       System.out.println(userBean);*/
       //通过构造器创建对象
       //String name, int id, int age, String hobby
      /* Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class, String.class);
       UserBean userBean = (UserBean)constructor.newInstance("陈磊",001,24,"打篮球");
       System.out.println(userBean);*/
       //通过反射调用方法
     /* UserBean userBean = (UserBean) c1.newInstance();
       Method declaredMethod = c1.getDeclaredMethod("setHobby", String.class);
       //invoke:激活的意思 (对象,方法的值)
       declaredMethod.invoke(userBean, "踢足球");
       System.out.println(userBean.getHobby());*/
       //通过反射操作属性
       UserBean userBean = (UserBean) c1.newInstance();
       Field age = c1.getDeclaredField("age");
       //不能直接操纵私有属性,需要关闭程序安全检测
       age.setAccessible(true);
       age.set(userBean,24);
       System.out.println(userBean.getAge());


  }
}

setAccessible

  • Mehthod、Filed、Constructor对象都有setAccessible()方法

  • 作用是关闭检测

  • 参数为true则指反射的对象在使用时应该取消Java语言访问检查

    • 提高反射效率,如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true

    • 使得原本无法访问的私有成员可以访问

  • 参数为false则指示反射的对象应该实施Java语言 访问检查

性能对比分析

package demo05;

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

public class Test04 {
    public static void add01(){
        //创建对象调用
        long start = System.currentTimeMillis();
        User user = new User();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long end = System.currentTimeMillis();
        System.out.println("正常方式"+(end-start)+"ms");
        System.out.println("===================================");
    }
    public static void add02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //反射调用
        User user1 = new User();
        Class c1 = user1.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user1,null);
        }
        long end = System.currentTimeMillis();
        System.out.println("正常方式"+(end-start)+"ms");
        System.out.println("===================================");
    }
    public static void add03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //通反射调用 关闭检测
        User user2 = new User();
        Class c1 = user2.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user2,null);
        }
        long end = System.currentTimeMillis();
        System.out.println("关闭检测"+(end-start)+"ms");
    }
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        add01();
        add02();
        add03();
    }
}

联系ORM

  • ORM-->对象关系映射

  • 类和表结构对应

  • 属性和字段对应

  • 对象和记录对应

小结

  • 自定义注解使用@interface自定义java.lang.annotation.Annotation接口

  • @Target:用于描述注解的适用范围,(即所描述的注解可以用在什么地方)

  • @Retenion:表示需要在什么级别白村该注释信息,用于描述注解的生命周期

  • @Document:说明该注解将被包含到javadoc中

  • @Inherited:说明子类可以继承父类中的该注解

反射相关的主要API

  1. java.lang.Class

  2. java.lang.reflect.Method

  3. java.lang.reflect.Field

  4. java.lang.reflect.Construction

  5. .......

类加载器作用

类加载器作用是用来把类装进内存的。JVM规范定义了如下类型的类加载器。

  • 引导类加载器(扩展类加载器的父类,也叫根类)

  • 扩展类加载器(系统类加载器的父类)

  • 系统类加载器

package demo06;
/*
//获得路径
D:\Environment\jdk\jre\lib\charsets.jar;
D:\Environment\jdk\jre\lib\deploy.jar;
D:\Environment\jdk\jre\lib\ext\access-bridge-64.jar;
D:\Environment\jdk\jre\lib\ext\cldrdata.jar;
D:\Environment\jdk\jre\lib\ext\dnsns.jar;
D:\Environment\jdk\jre\lib\ext\jaccess.jar;
D:\Environment\jdk\jre\lib\ext\jfxrt.jar;
D:\Environment\jdk\jre\lib\ext\localedata.jar;
D:\Environment\jdk\jre\lib\ext\nashorn.jar;
D:\Environment\jdk\jre\lib\ext\sunec.jar;
D:\Environment\jdk\jre\lib\ext\sunjce_provider.jar;
D:\Environment\jdk\jre\lib\ext\sunmscapi.jar;
D:\Environment\jdk\jre\lib\ext\sunpkcs11.jar;
D:\Environment\jdk\jre\lib\ext\zipfs.jar;
D:\Environment\jdk\jre\lib\javaws.jar;
D:\Environment\jdk\jre\lib\jce.jar;
D:\Environment\jdk\jre\lib\jfr.jar;
D:\Environment\jdk\jre\lib\jfxswt.jar;
D:\Environment\jdk\jre\lib\jsse.jar;
D:\Environment\jdk\jre\lib\management-agent.jar;
D:\Environment\jdk\jre\lib\plugin.jar;
D:\Environment\jdk\jre\lib\resources.jar;
D:\Environment\jdk\jre\lib\rt.jar;
C:\Users\16225\IdeaProjects\javaEE\out\production\javaEE;
C:\Users\16225\IdeaProjects\javaEE\src\lib\commons-io-2.6.jar;
D:\idea\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar
 */
public class Test03 {
    
    public static void main(String[] args) throws ClassNotFoundException {
        long start = System.currentTimeMillis();
        //获得系统类的加载器
        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("demo06.Test03").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"));
        long end = System.currentTimeMillis();
        System.out.println("时间为"+(end-start)+"毫秒");
    }
}

 

posted @ 2020-04-14 09:43  Crazylearningjava  阅读(350)  评论(0)    收藏  举报