反射常见提问及记录

4 篇文章 0 订阅
1.    写出获取Class实例的三种常见方式

    获取Class类对象(实例)的三种方式
    - 类名.class属性
         Class<Student> c1 = Student.class;
    - 对象名.getClass()方法
         Student s = new Student();
         Class<? extends Student> c3 = s.getClass();
    - Class.forName(全类名)方法
        Class<?> c4 = Class.forName("com.itheima_02.Student");
        
2.    谈谈你对Class类的理解
    1.类的加载过程:
    程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。
    接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件
    加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此
    运行时类,就作为Class的一个实例。
    2.换句话说,Class的实例就对应着一个运行时类。
    3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式
    来获取此运行时类。

反射

      反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java类的Class类显示要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。

      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以的得到这些实例对象

3. 利用反射和重载完成以下功能
1)创建Student类,类中有属性name和age并封装属性
2)重载Student的构造函数,一个是无参构造并,另一个是带两个参数的有参构造,要求在构造函数打印提示信息 
3)创建带main函数的NewInstanceTest类,利用Class类得到Student对象
4)通过上述获取的Class对象分别调用Student有参函数和无参函数

     a. 使用对象名.getClass()方法 获取class实例

打印出来的是存储地址

代码和 打印结果:

package com.B.Reflect_15.Ask_03;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
//3)创建带main函数的NewInstanceTest类,利用Class类得到Student对象
       // a.-对象名.getClass()方法 获取class实例
        Student s1 = new Student();
        Class<? extends Student> c = s1.getClass();

//       此乃提示信息!
//com.B.Reflect_15.Ask_03.Student@6bdf28bb
//----------
//com.B.Reflect_15.Ask_03.Student@6b71769e
//
//进程已结束,退出代码 0
/

//        4)通过上述获取的Class对象分别调用Student有参函数和无参函数
//调用无参函数并创建对象obj
        Constructor<?> constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        //调用带参函数并创建对象obj1
        Constructor<?> constructor1 = c.getConstructor(String.class, int.class);
        Object obj1 = constructor1.newInstance("知谓忧",22);

        System.out.println(obj);
        System.out.println("----------");
        System.out.println(obj1);
    }
}
此乃提示信息!
com.B.Reflect_15.Ask_03.Student@6bdf28bb
----------
com.B.Reflect_15.Ask_03.Student@6b71769e

进程已结束,退出代码 0
  b.- Class.forName(全类名)方法  获取class实例

打印出来依旧是地址

package com.B.Reflect_15.Ask_03;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
//3)创建带main函数的NewInstanceTest类,利用Class类得到Student对象

//        b.- Class.forName(全类名)方法  获取class实例
        Class<?> c1 = Class.forName("com.B.Reflect_15.Ask_03.Student");

//        4)通过上述获取的Class对象分别调用Student有参函数和无参函数
//调用无参函数并创建对象obj
        Constructor<?> constructor = c1.getConstructor();
        Object obj = constructor.newInstance();
        //调用带参函数并创建对象obj1
        Constructor<?> constructor1 = c1.getConstructor(String.class, int.class);
        Object obj1 = constructor1.newInstance("知谓忧",22);

        System.out.println(obj);
        System.out.println("----------");
        System.out.println(obj1);
    }
}
此乃提示信息!
com.B.Reflect_15.Ask_03.Student@6bdf28bb
----------
com.B.Reflect_15.Ask_03.Student@6b71769e

进程已结束,退出代码 

  1. 利用通过反射修改私有成员变量

    1. 定义PrivateTest类,有私有name属性,并且属性值为hellokitty,只提供name的getName的公有方法

    2. 创建带有main方法ReflectTest的类,利用Class类得到私有的name属性

    3. 修改私有的name属性值,并调用getName()的方法打印name属性值

 代码:

package com.B.Reflect_15.Ask_01;
//1.	定义PrivateTest类,有私有name属性,并且属性值为hellokitty,只提供name的getName的公有方法
public class PrivateTest {
    private String name = "hellokitty";

    public PrivateTest() {
    }

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

    public String getName() {
        return name;
    }
}



package com.B.Reflect_15.Ask_01;

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

//2.	创建带有main方法ReflectTest的类,利用Class类得到私有的name属性
public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//- Class.forName(全类名)方法  获取class实例对象
        Class<?> c = Class.forName("com.B.Reflect_15.Ask_01.PrivateTest");

// 3.	修改私有的name属性值,并调用getName()的方法打印name属性值
        //创建运行时类的对象
        PrivateTest pri= (PrivateTest) c.newInstance();

        //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name = c.getDeclaredField("name");

        //2.保证当前属性是可访问的
        //暴力反射,适用于私有构造方法/对象
        //public void setAccessible(boolean flag):值为true,取消访问检查
        name.setAccessible(true);

        //3.获取、设置指定对象的此属性值
        name.set(pri,"臭小子");

        System.out.println(pri.getName());
    }
}

  • 2.利用反射和File完成以下功能

    1. 利用Class类的forName方法得到File类

    2. 在控制台打印File类的所有构造器

    3. 通过newInstance的方法创建File对象,并创建D:\mynew.txt文件 */

报错!

Exception in thread "main" java.lang.NoSuchMethodException: com.B.Reflect_15.Ask_03.Student.<init>(java.lang.String)
	at java.base/java.lang.Class.getConstructor0(Class.java:3349)
	at java.base/java.lang.Class.getConstructor(Class.java:2151)
	at com.B.Reflect_15.Ask_02.FileDemo.main(FileDemo.java:24)

 最后查看资料后发现出错点在

- Class.forName(全类名)方法  获取class实例对象

这一步,类名错误,改过来就运行正确了

public java.io.File(java.lang.String,java.lang.String)
public java.io.File(java.io.File,java.lang.String)
private java.io.File(java.lang.String,java.io.File)
private java.io.File(java.lang.String,int)
public java.io.File(java.net.URI)
public java.io.File(java.lang.String)

进程已结束,退出代码 0

 完整代码:

package com.B.Reflect_15.Ask_02;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//利用反射和File完成以下功能
//	1.	利用Class类的forName方法得到File类
//	2.	在控制台打印File类的所有构造器
//	3.	通过newInstance的方法创建File对象,并创建D:\mynew.txt文件
public class FileDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//- Class.forName(全类名)方法  获取class实例对象
//        Class<?> cla = Class.forName("com.B.Reflect_15.Ask_03.Student");
        Class cla = Class.forName("java.io.File");
//获取File的所有构造器并输出
        Constructor[] con = cla.getDeclaredConstructors();
        for (Constructor c : con) {
            System.out.println(c);
        }

        //获取File的一个构造器
        Constructor<?> constructor = cla.getConstructor(String.class);
        //用上面得到构造器创建File对象
        File file = (File) constructor.newInstance("D:\\mynew.txt");
        //获取File的createNewFile方法
        Method method = cla.getMethod("createNewFile");
        //通过createNewFile方法,File对象,完成文件的创建
        method.invoke(file);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值