Java注解和反射,Java教程马士兵全集

public User() {

}



public User(String name, int id, int age) {

    this.name = name;

    this.id = id;

    this.age = age;

}

}




**Class类**:一个Class对象宝华了特定某个结构的有关信息



1.  Class对象只能由系统建立

2.  一个加载的类在JVM中只会有一个Class实例,一个Class对象对应的是一个加载到JVM中的.class文件

3.  Class类是Reflection的根源,针对任何想动态加载的类,必须获得Class对象



### [](https://gitee.com/vip204888/java-p7)2.1 获取Class类的实例



1.  已知具体类,通过类的class属性获取,最安全,性能最高(Class c = Person.class;)

2.  已知某个类的实例,调用该实例的getClass()方法获取Class对象(Class c = person.getClass()😉

3.  已知一个类的全类名,且该类在类路径下,通过Class类的静态方法forName() 获取,需要抛出异常

4.  内置基本数据类型直接使用类名.Type

5.  利用ClassLoader



*   数组只要元素类型与维度一样,就是同一个class



[](https://gitee.com/vip204888/java-p7)2.2 Java 内存

----------------------------------------------------------------------



*   堆:存放new出来的对象和数组;可以被所有线程共享,不存放别的对象引用

    

*   栈:存放基本变量类型;存放引用对象的变量(此引用在堆的具体地址)

    

*   方法区:可以被所有线程共享;包含所有的class和static变量

    



类的加载过程:



1.  类的**加载(Load)**

    

    *   将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后**生成一个代表该类的java.lang.Class对象**

    *   类加载器把类(class)装载进内存。有**引导类加载器**(Bootstap Classloader)(JVM自带,C++编写,负责Java平台核心库,无法直接获取),**扩展类加载器**(Extension Classloader)(负责jre/lib/ext目录下的jar包装入工作库),**系统类加载器**(System Classloader)(负责java -classpath所指的目录下的类与jar包装入,最常用的加载器)

    *   双亲委派机制确保类的正确加载

    

    ```

    //类加载器演示

    public class ClassLoaderDemo {

        public static void main(String[] args) throws ClassNotFoundException {

            //获取系统类的加载器

            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("com.jayz.annotationDemo.ClassLoaderDemo").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"));

        }

    } 

    ```

2.  类的链接(Link)

    

    *   将Java类的二进制代码合并到JVM运行环境中

        *   验证:确保加载的类信息符合JVM规范,没有安全问题

        *   准备:正式**为类变量(static)分配内存并设置类变量默认初始值**,内存都将在方法区中分配。

        *   解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程

3.  类的初始化(Initialize)

    

    *   **执行类构造器()方法的过程。类构造器方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生**(不是类对象的构造器)

        

    *   初始化一个类时,若发现其父类还没有初始化,先触发其父类的初始化

        

    *   虚拟机保证一个类的()方法在多线程环境中被正确加锁和同步。

        

    *   发生类的初始化(类的主动应用),被动引用不会。

        

        1.  主动引用:当虚拟机启动时,先初始化main方法所在的类

        

        *   new 一个类的对象

        *   调用类的静态方法和静态成员

        *   使用java.lang.reflect包中的方法对类进行反射调用

        *   初始化一个类,若其父类没有被初始化,先初始化父类

        

        2.  被动引用

            *   访问一个静态域时,只有真正声明这个域的类才会被初始化(如子类引用父类的静态变量,不会导致子类初始化)

            *   通过数组定义类引用,不会触发此类的初始化

            *   引用常量不会触发初始化(常量在链接阶段存入常量池)



public class InitiDemo {

static {

    System.out.println("Main所在类加载");

}



public static void main(String[] args) throws ClassNotFoundException {

    //1.主动引用

    //Son son = new Son(); //Main所在类加载 父类被加载 子类被加载



    // 反射

    //Class.forName("com.jayz.annotationDemo.Son");//Main所在类加载 父类被加载 子类被加载



    //被动引用

    //System.out.println(Son.b);//Main所在类加载 父类被加载 2

    Son[] sons = new Son[5]; //Main所在类加载

}

}

class Father{

static int b = 2;



static{

    System.out.println("父类被加载");

}

}

class Son extends Father{

static {

    System.out.println("子类被加载");

    m = 300;

}



static int m = 100;

static final int M = 1;

}




### [](https://gitee.com/vip204888/java-p7)2.3 类信息



示例:获取类相关信息(方法,属性,构造器,父类,接口,注解)



//获取类的信息

public class ClassInformation {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {

    Class c1 = Class.forName("com.jayz.annotationDemo.User");



    //获得类的名字

    System.out.println(c1.getName()); //获得包名+类名

    System.out.println(c1.getSimpleName()); //获得类名



    //获得类的属性

    Field[] fields = c1.getFields(); //只能找到 public 属性

    fields = c1.getDeclaredFields(); //

    for(Field field:fields) {

        System.out.println(field);

    }



    //获得指定属性的值

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

    }



    //获得构造器方法

    Constructor constructor = c1.getConstructor();

    Constructor[] constructors = c1.getConstructors();

}

}




示例:\*\*通过反射构造对象,调用方法和属性(私有的,setAccessible(true))。\*\*使用反射会影响程序效率。



//反射操作

public class ReflectionDemo02 {

public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

    //获得Class对象

    Class c1 = Class.forName("com.jayz.annotationDemo.User");



    //构造对象

    User u1 = (User)c1.newInstance();  //调用类的无参构造器,若定义了有参构造,没有定义无参构造,无法使用此方法

    System.out.println(u1);



    //通过构造器创建对象

    Constructor constructor = c1.getConstructor(String.class, int.class, int.class);

    User u2 = (User)constructor.newInstance("jay", 01, 18);

    System.out.println(u2);



    //通过反射调用普通方法

    User u3 = (User)c1.newInstance();

    Method setName = c1.getDeclaredMethod("setName", String.class);



    //invoke 激活方法

    setName.invoke(u3,"jay2");

    System.out.println(u3.getName());



    //反射操作属性

    User u4 = (User)c1.newInstance();

    Field name = c1.getDeclaredField("name");//访问私有属性,权限不够

    //关闭权限

    name.setAccessible(true);

    name.set(u4,"jay3");

    System.out.println(u4.getName());

}

}




### [](https://gitee.com/vip204888/java-p7)2.4 ORM (Object relation Mapping):利用注解和反射完成类和表结构的映射关系



public class ORM_Demo {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

    Class c1 = Class.forName("com.jayz.annotationDemo.Student01");



    //通过反射获得注解

    Annotation[] annotations = c1.getAnnotations();

    for (Annotation annotation : annotations) {

        System.out.println(annotation);

    }



    //获得注解的 value的值

    TableJay tableJay = (TableJay)c1.getAnnotation(TableJay.class);

    String value = tableJay.value();

    System.out.println(value);



    //获得类指定的注解

    Field name = c1.getDeclaredField("name");

    FieldJay fieldJay = name.getAnnotation(FieldJay.class);

    System.out.println(fieldJay.columnName());

    System.out.println(fieldJay.length());

    System.out.println(fieldJay.type());

}

}

最后

再免费分享一波我的JAVA架构专题面试真题+解析+JAVA学习书籍:戳这里免费领取

image.png

();

    System.out.println(value);



    //获得类指定的注解

    Field name = c1.getDeclaredField("name");

    FieldJay fieldJay = name.getAnnotation(FieldJay.class);

    System.out.println(fieldJay.columnName());

    System.out.println(fieldJay.length());

    System.out.println(fieldJay.type());

}

}

最后

再免费分享一波我的JAVA架构专题面试真题+解析+JAVA学习书籍:戳这里免费领取

[外链图片转存中…(img-mPfcaX1M-1628674789011)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值