java个人笔记-反射机制

反射机制有什么用?

通过java语言中的反射机制可以操作字节码文件,让代码更具通用性(更灵活),可变化的内容都是写到配置文件当中,将来修改配置文件文件之后,创建的对象不一样了,调用的方法也不同,但是java代码不需要要做任何改动。

反射机制的优缺点:
 优点: 运行期类型的判断,动态加载类,提高代码灵活度。
 缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

反射机智的相关类在哪个包下?

java.lang.Reflect.*;

反射机制相关的类有哪些?(重要的类)

java.lang.class 代表整个字节码
java.lang.reflect.Method 代表字节码中的方法字节码
java.lang.reflect.Constructor 代表字节码中的构造方法字节码
java.lang/reflect.Field 代表字节码中的属性字节码

获取一个类的字节码class

获取一个类的字节码有三种方法:
Class c = Class.forName("");
Class c = 引用.getClass();
Class c = 任何类型.class
获取Class(类)

获取类的三种方法,代码实例:

public class ReflectTest01 {
    public static void main(String[] args){
        Class c1=null;
        /*
        第一种方法
        Class.forName()
        1.静态方法
        2.参数是一个字符串
        3.字符串需要的是一个完整类名
         */
        try {
            //c1代表String.class文件(或者说代表String类型)
            c1=Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        /*
        第二种方法
        java中任何一个对象都有一个方法:getClass()
         */
        String s="abc";
        //x代表String.class字节码文件,x代表String类型
        Class x=s.getClass();
        System.out.println(c1==x);//true

        /*
        第三种方法
        java语言中任何一种类型,都有.class属性
         */
        //a代表String类型
        Class y= String.class;//a代表String类型
        System.out.println(x==y);//true
    }
}

通过Class的newInstance()方法来实例化对象
注意:newInstance()方法内部实际上调用了无参构造方法,必须保证无参构造存在才行

代码实例:
创建User类:

public class User {
    public User() {
        System.out.println("无参数构造方法执行");
    }
}

测试类:

public class ReflectTest02 {
    public static void main(String[] args) {
        try {
            //通过反射机制,获取Class,通过Class来实例化对象
            Class c=Class.forName("bean.User");
            //newInstance()会调用User这个类的无参构造方法创建对象
            Object obj=c.newInstance();
            System.out.println(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}
无参数构造方法执行
bean.User@14ae5a5

Tip:如果只希望一个类的静态代码块执行,其他代码不执行可以使用:
 class.forName(“完整类名”) 
 该方法执行会导致类加载,静态代码块在类加载时执行

通过反射机制访问对象的属性Field

创建Student类

//反射属性field
public class Student {
    public int no;
}

测试类

注意:给对象的某个属性赋值的三要素:对象、属性、实参

public class ReflectTest06 {
    public static void main(String[] args) throws Exception{
        Class thisClass=Class.forName("bean.Student");

        //实例化一个对象(无参构造)
        Object obj = thisClass.newInstance();
        //获取某个属性no
        Field noFiled = thisClass.getDeclaredField("no");
        //给obj对象的no赋值
        //三要素:对象、属性、实参
        noFiled.set(obj,2222);

        System.out.println(noFiled.get(obj));

    }
}

通过反射机制访问对象的方法Method

创建UserService类

public class UserService {

    public boolean login(String name,String password){
        if ("admin".equals(name)&&"123".equals(password)){
            return true;
        }
        return false;
    }

    public void logout(){
        System.out.println("成功退出");
    }
}

创建测试类
注意:调用某个对象的方法的四要素:对象、方法名、返回值、实参

import java.lang.reflect.Method;
/*
重点:通过反射机制怎么调用一个对象的方法
 */
public class ReflectTest07 {
    public static void main(String[] args) throws Exception{
        Class userServiceClass=Class.forName("bean.UserService");

        //实例化对象
        Object obj=userServiceClass.newInstance();

        //获取方法(方法名+参数)
        Method method=userServiceClass.getDeclaredMethod(
                "login",String.class,String.class);

        //调用方法
        //四要素:对象、方法名、返回值、实参
        Object returunMethod=method.invoke(obj,"admin","123");

        System.out.println(returunMethod);//true
    }
}

通过反射机制调用一个对象的构造方法Constructor

创建Vip类

public class Vip {
    String name;
    String password;

    public Vip() {
    }

    public Vip(String name, String password) {
        this.name = name;
        this.password = password;
    }

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

创建测试类:

import java.lang.reflect.Constructor;
/*
重点:通过反射机制怎么调用一个对象的构造方法实例化对象
 */
public class ReflectTest08 {
    public static void main(String[] args) throws Exception{
        Class c=Class.forName("bean.Vip");

        //获取构造方法
        Constructor con=c.getConstructor(String.class,String.class);
        //调用构造方法new对象
        Object newObj=con.newInstance("a123","123");

        System.out.println(newObj);
    }
}

获取一个类的父类,和所有接口

一个类的父类只有一个,接口可能有多个
所以获取接口返回的是个数组

public class ReflectTest09 {
    public static void main(String[] args) throws Exception{
        Class c=Class.forName("java.lang.String");

        //获取父类
        System.out.println(c.getSuperclass());

        //获取接口
        Class[] classes=c.getInterfaces();
        for(Class in:classes){
            System.out.println(in.getName());
        }
    }
}

关于通用的获取文件绝对路径

前提:文件必须在类路径下

import java.io.InputStream;
import java.util.Properties;

public class AboutPath {
    public static void main(String[] args) throws Exception {
        //这种方式获取文件绝对路径是通用的
        //以下通用方式的前提是:必须在同一个类的根路径下(src)
        String path=Thread.currentThread()
                .getContextClassLoader()
                .getResource("bean\\classinfo.properties")
                .getPath();

        //或者直接以流的形式返回
        InputStream path2=Thread.currentThread()
                .getContextClassLoader()
                .getResourceAsStream("bean\\classinfo.properties");

        System.out.println(path);
        System.out.println(path2);
    }
}

关于资源绑定器

java.util包下提供了一个资源绑定器,便于获取【属性配置文件】中的内容。
使用以下方法,属性配置文件必须放在类路径下

创建属性配置文件:classinfo.properties

className=bean.User

测试类

import java.util.ResourceBundle;

public class ResourceBundleTest {
    public static void main(String[] args){
        //只能绑定.properties文件
        //路径扩展名省略
        ResourceBundle bundle=ResourceBundle.getBundle("bean\\classinfo");
        String className=bundle.getString("className");
        System.out.println(className);//bean.User
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值