zoukankan      html  css  js  c++  java
  • Java-反射

    Java-反射

    文章推荐

    https://blog.csdn.net/ju_362204801/article/details/90578678

    有视频,非常好理解,强烈推荐

    简单理解

    类是一个模板,用于描述一类对象的行为和状态,对象是类的一个实例,有状态和行为。类对象,是用于描述这种类,都有什么属性、方法的。

    反射是从Class类对象开始,因为万物皆可对象,代码存储在.java文件中,编译得到.class文件,用于执行,即这些class文件就是Class类。反射就是对这个这个Class类进行 “解剖” ,感觉这个词用的很形象。“解剖” 是在Class类对象中,利用反射把一个类的成员变量、方法、属性等信息,映射成一个个对象。然后对对象进行操作。

    反射主要是用于框架(尤其是Spring框架)和工具开发,是框架设计的关键,但耗性能。当需要切换调用业务方法,可以不需要修改代码,不需要重新编译,只修改对应配置文件,通过反射调用,实现切换调用另外的业务方法。

    获取类对象

    使用反射先要得到想反射的类,有多种方法获得Class对象。

    1. Class.forName
    2. Test_Main.class
    3. new Test_Main().getClass()

     需要抛出多种异常

        //三种获取Class类的方法
        public void test1() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
        }
    
        public void test2() throws Exception{
            Class tClass = Test_Main.class;
        }
    
        public void test3() throws Exception{
            Class tClass = new Test_Main().getClass();
        }

     Class实例: 就是指JVM中一份字节码,一个类在JVM中只有一份字节码。在一个JVM中,一种类,只会有一个类对象存在。所以不同方式取出来的类对象,都是一样的。

    Java创建对象

    另外Java创建对象的方法有很多。

    • 通过new语句实例化一个对象
    • 通过反射机制创建对象
    • 通过clone()方法创建对象
      • 在使用clone()方法,不会调用构造函数,而是需要有一个分配了内存的源对象。在创建新对象时,首先应该分配一个和源对象一样大的内存空间。
    • 通过反序列化的方式创建对象
      • 序列化就是把对象通过流的方式存储到文件里,那么反序列化就是把字节内容读出来,并还原成Java对象,这里还原的过程就是反序列化,使用反序列化时也不会调用构造方法。

     反射方法

    无参方法

        /*  m1() 无参方法
            public void m1(){
            System.out.println("m1");
        }
         */
        @Test
        public void test1() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Test_Main test_main = (Test_Main)tClass.newInstance(); //新建实例
            Method m1 = tClass.getMethod("m1",null); //输入空值
            m1.invoke(test_main,null); //调用实例和输入值
        }

    含参方法

        /*  m2():
            public void m2(String name){
            System.out.println(name);
        }
         */
        @Test
        public void test2() throws Exception{
            Class tClass = Test_Main.class;
            Test_Main test_main = (Test_Main)tClass.newInstance();
            Method m2 = tClass.getMethod("m2", String.class);
            m2.invoke(test_main,"tom");//输出tom
        }

    有返回类型和多参数方法

        /*
            public String m4(String name ,int age){
            return name+age;
        }
         */
        @Test
        public void test4() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Test_Main test_main = (Test_Main) tClass.newInstance();
            Method m4 = tClass.getMethod("m4", String.class, int.class);
            String returnValue = (String) m4.invoke(test_main,"jerry",5); //返回类型
            System.out.println(returnValue); //打印jerry5
        }

    private 方法

    反射private 方法会显示带锁,需要使用 getDeclaredMethod 方法调用,设置对象的Accessible的访问标志位为true,就可以通过反射获取私有变量。

        /*
        private void m3(){
            System.out.println("m3");
        }
         */
        @Test
        public void test3() throws Exception{
            Class tClass = new Test_Main().getClass();
            Test_Main test_main = (Test_Main)tClass.newInstance(); //新建实例
            Method m3 = tClass.getDeclaredMethod("m3",null); //强制访问
            m3.setAccessible(true); //设置访问标志位为 True
            m3.invoke(test_main,null); //打印m3
        }

    static方法

    不需要新建实例,直接获取方法。

        /*  static 方法
            public static void m5(){
            System.out.println("m5");
        }
         */
        @Test
        public void test5() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Method m5 = tClass.getMethod("m5",null); //没有返回值
            m5.invoke(null,null); // 没有实例化对象,无输入参数 打印m5
        }

    反射属性和反射构造函数方法都是使用类似方法步骤。

     反射属性字段

        //属性字段
        public String name = "Paige";
        public static int id = 147;
        private int age = 5;

    获取/修改属性

        @Test
        public void test1() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Test_Main test_main = (Test_Main) tClass.newInstance(); //新建实例
    
            Field field1 = tClass.getField("name"); //获取属性
            String returnValue = (String) field1.get(test_main); //通过get获取属性
            System.out.println(returnValue); //打印出:Paige
    
            field1.set(test_main,"tom"); //set修改属性
            System.out.println(field1.get(test_main)); //打印出:tom
        }

    private属性

            Field field2 = tClass.getDeclaredField("age");
            field2.setAccessible(true); //private属性同样需要强制访问
            System.out.println(field2.get(test_main)); //打印出:5

    static属性

            Field field3 = tClass.getField("id");
            System.out.println(field3.get(null)); //static 同样不需要实例,设置为null即可 //打印出:147

    反射构造函数方法都是使用类似方法步骤,只是使用方法不同。

    反射构造方法

    无参构造方法

        /*
            public Test_Main() {
            System.out.println("无参构造方法");
        }
         */
        @Test
        public void test_constructor1() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Constructor constructor1 = tClass.getConstructor(null); //得到无参构造函数
            constructor1.newInstance(null); //用构造方法创建对象
        }

    一个参数

        /*
            public Test_Main(String name) {
            this.name = name;
            System.out.println("name:"+name);
        }
         */
        @Test
        public void test_constructor2() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Constructor constructor1 = tClass.getConstructor(String.class); //得到String构造函数
            constructor1.newInstance("tomas"); //用构造方法创建对象,输出name: tomas
        }

    多个参数

        /*
        public Test_Main(String name, int age) {
            this.name = name;
            this.age = age;
            System.out.println("name: "+name+" age: "+age);
        }
     */
        @Test
        public void test_constructor3() throws Exception{
            Class tClass = Class.forName("com.hut.djh.Test_Main");
            Constructor constructor1 = tClass.getConstructor(String.class,int.class); //得到String、int构造函数
            constructor1.newInstance("tomas",58); //用构造方法创建对象,输出name: tomas age: 58
        }

    源码

  • 相关阅读:
    POJ 1166 The Clocks 高斯消元 + exgcd(纯属瞎搞)
    防止登录页面出如今frame中
    android--显式跳转和隐式跳转的差别使用方法
    卫星照片
    poj 2586 Y2K Accounting Bug (贪心)
    【转】关于Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定文件编码类型
    【转】在Eclipse中使用PyDev进行Python开发
    【转】eclipse + Pydev 配置Python开发环境
    【转】Python自动化测试 (一) Eclipse+Pydev 搭建开发环境
    【转】Eclipse的启动问题【an error has occurred see the log file】
  • 原文地址:https://www.cnblogs.com/djhzzl/p/14351476.html
Copyright © 2011-2022 走看看