Java反射机制 ,获取Class/Field/Method ,通过读属性文件实例化对象(框架思想),只执行类中的静态代码块,获取类路径下文件的绝对路径,资源绑定器,反射机制给属性赋值,可变长度参数

一、反射机制的作用:

  1. 通过java语言中的反射机制可以操作字节码文件。
  2. 通过java语言中的反射机制可以操作class文件。
  3. 可以让程序变得更加灵活。

二、反射机制相关类:

  • java.lang.Class代表整个字节码
  • java.lang.reflect.Method代表字节码中的方法字节码
  • java.lang.reflect.Constructor代表字节码中的构造方法字节码
  • java.lang.reflect.Field代表字节码中的属性字节码
public class Test{
    //Field
    int no;
    //Constructor
    public Test(){

    }
    //Method
    public void dosome(){

    }
}

三、获取Class的方法:

  1. Class.forName(“完整类名”);
    (1)静态方法。
    (2)方法的参数是一个字符串。
    (3)字符串去要填一个完整的类名。
    (4)完整类名必须带有包名。
    例如:Class c1 = Class.forName(“java.lang.String”);
  2. 对象.getClass();
    (1)Object类中的方法,java中任何对象都有这个方法。
    例如:Class c1 = s.getClass();
  3. 数据类型.class;
    (1)任何类型都有class属性。
    例如:Class c1 = int.class;

四、反射机制动态实例化对象:

1. 反射机制实例化对象:

public class Test{
    public static void main(String[] args) {
        Class c = null;
        try {
            c = Class.forName("java.lang.String");//通过反射机制获取Class
            Object obj = c.newInstance();//通过Class实例化对象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        /*等同于*/
        String s = new String();
    }
}

注意:newInstance()方法是通过调用c的无参数构造方法实例化对象,必须保证无参数构造方法存在。如果只定义有参数构造方法,无参数构造方法就没了,这种方法创建对象时就会报错。

2. 通过读属性文件实例化对象:

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class Test{
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        FileReader fr = new FileReader("javase/src/myfile");//通过IO流读取文件
        Properties pro = new Properties();//IO和Properties联合使用(文章)
        pro.load(fr);
        fr.close();
        String s = pro.getProperty("class");
        Class c = Class.forName(s);
        Object obj = c.newInstance();
        System.out.println(obj);
    }
}

在这里插入图片描述
不需要改变java代码,通过修改myfile文件内容就可以创建不同对象。
框架思想。

五、如何不实例化对象,只执行类中的静态代码块:

public class Test{
    public static void main(String[] args) throws ClassNotFoundException {
        Class c = Class.forName("Test1");
    }
}
class Test1{//右键类名,copy->copy reference复制类的完整类名
    static{
        System.out.println("静态代码块执行");
    }
}

六、如何获取类路径src下文件的绝对路径:重点

 String path = Thread.currentThread().getContextClassLoader().getResource("myfile").getPath();

在这里插入图片描述
name变量从类的根路径src下作为起点。
适合各种操作系统,Linux也适用。

七、如何获取类路径src下文件的流:重点

 InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("myfile");

八、资源绑定器:重点

用于根据key值获取属性配置文件中value值。

import java.util.ResourceBundle;

public class Test{
    public static void main(String[] args) {
        ResourceBundle bundle = ResourceBundle.getBundle("myfile");
        String s = bundle.getString("name");
        System.out.println(s);
    }
}

只能用于.properties文件且文件必须位于类路径下。

九、获取Field:重点

  1. 获取属性类型
  2. 获取属性名
  3. 获取属性修饰符
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test{
    public static void main(String[] args) throws ClassNotFoundException {
        Class c = Class.forName("Test1");//获取类
        //Field field[] = c.getFields();//获取所有public属性,返回Field数组
        Field field[] = c.getDeclaredFields();//获取所有属性,返回Field	数组
        for(Field fd:field){
            //获取属性类型
            Class fieldType = fd.getType();//返回Class类型
            String fType = fieldType.getSimpleName();
            System.out.println(fType);
            //获取属性名字
            String fName = fd.getName();//返回String类型
            System.out.println(fName);
            //获取属性修饰符
            int fieldModifiers = fd.getModifiers();//返回int类型
            String fModifiers = Modifier.toString(fieldModifiers);
            System.out.println(fModifiers);
        }
    }
}
class Test1{
    public int a;
    private double b;
    protected String c;
}

十、反射机制给属性赋值:重点

import java.lang.reflect.Field;

public class Test{
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class TestClass = Class.forName("TestClass");//创建类
        Object test = TestClass.newInstance();//创建对象
        Field a1 = TestClass.getDeclaredField("a");//根据属性名获取属性
        a1.set(test,123);//给test对象的a1属性赋值123,不能访问私有属性
        a1.get(test);//获取test对象的a1属性的值

        Field a2 = TestClass.getDeclaredField("is");//根据属性名获取属性
        a2.setAccessible(true);//打破封装,使得该私有属性可以访问
        a2.set(test,false);//给test对象的a1属性赋值123,不能访问私有属性
        a2.get(test);//获取test对象的a1属性的值
    }
}
class TestClass {
    public int a;
    private boolean is;
    protected  double b;
}

十一、可变长度参数:

public class Test{
    public static void m(int ...args){//可变长参数语法,可变长参数只能有一个,必须出现在参数最后一个位置,可看做数组
        for (int i=0;i<args.length;i++){
            System.out.println(args[i]);
        }
    }
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        m();
        m(12,13);
        m(1,2,4,0);
    }
}

十二、获取Method:

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test{
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("TestClass");//创建类
        Method[] methods = c.getDeclaredMethods();//获取方法
        for (Method method :methods){
            //获取修饰符
            int m = method.getModifiers();
            String s1 = Modifier.toString(m);
            //获取返回值类型
            Class n = method.getReturnType();
            String s2 = n.getSimpleName();
            //获取方法名
            String s3 = method.getName();
            //获取参数类型
            Class[] types = method.getParameterTypes();
            for(Class parameter:types){
               String s4 = parameter.getSimpleName();
            }
        }
    }
}
class TestClass{
    public void m1() {

    }
}

十三、通过反射机制调用对象的方法:重点

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * invoke方法的使用:。
 * 实际上invoke方法的使用,和我们常见的有所区别。
 * 我们经常创建一个对象A,A对象里面的方法getA()方法,然后A.getA()
 * 我们采用新的方式调用:
 * (1)弄一个方法的“替身”(其实就是构建一个Method对象,让这个Method对象来代替你现在要用的方法)
 * (2)然后给替身需要的对象和参数,让替身去替你调用
 */
public class Test{
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class c = Class.forName("TestClass");//创建类
        Object o = c.newInstance();//创建对象
        Method method = c.getDeclaredMethod("m1",String.class,int.class);//根据c类的方法名和参数类型获取某个方法
        Object returnValue = method.invoke(o,"abc",123);//调用o对象的invoke方法给method方法传入参数“abc”和123得到method方法的返回值returnValue******重点********
    }
}
class TestClass{
    public void m1(String a1,int a2) {

    }
    public void m1(String a1){

    }
}


十四、通过反射机制调用构造方法:

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

public class Test{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("TestClass");//创建类
        Constructor c1 = c.getDeclaredConstructor(int.class,double.class);//通过类名和参数获取构造方法
        Object obj = c1.newInstance(12,10.1);//通过构造方法创建对象
        
        Object obj1 = c.newInstance();//通过无参构造方法创建对象
    }
}
class TestClass{
    int a;
    double b;

    public TestClass(int a, double b) {
        this.a = a;
        this.b = b;
    }
}

十五、通过反射机制获取父类和父接口:

public class Test{
    public static void main(String[] args) throws ClassNotFoundException {
        Class c = Class.forName("java.lang.String");//创建类
        //获取String类的父类
        Class superclass = c.getSuperclass();
        String s = superclass.getName();
        //获取String类的所有父接口
        Class[] interfaces = c.getInterfaces();
        for (Class i:interfaces) {
            String ss = i.getName();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姓蔡小朋友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值