Java中的反射机制基本运用详解

网友投稿 214 2022-10-01


Java中的反射机制基本运用详解

目录java中的反射机制基本运用1、什么是反射(reflect)2、反射机制提供的功能3、反射->获取类对象4、反射->利用无参构造实例化对象5、反射->利用有参构造实例化对象6、反射->调用无参方法7、反射->调用有参方法8、反射->访问私有方法9、反射->类加载路径总结

Java中的反射机制基本运用

看完反射可以了解一下注解

注解annotation://jb51.net/article/221276.htm

1、什么是反射(reflect)

反射是java的动态机制,它允许将对象的实例化,方案的调用,属性的操作等从编码期确定转移到程序运行期确定。

反射能大大提高代码的灵活度。但同时也带来了更多的系统开销和较慢的运行效率,因此程序不能过度依赖反射。

2、反射机制提供的功能

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象(实例化)

在运行时判断任意一个类所具有的成员变量和方法

在运行时调用任意一个对象的方法——动态代理

3、反射->获取类对象

在开始之前创建一个实体类,用于测试反射机制

package reflect_text;

/**

* 用于测试反射机制

*

* @author Akio

* @Create 2021/8/14 10:37

*/

public class Person {

private String name = "刘瑜澄";//设置初始值

private int age = 22;

public Person() {//无参构造

}

public Person(String name, int age) {//有参构造

this.name = name;

this.age = age;

}

public void sayHello() {//无参方法

System.out.println(name + ":使用sayHello方法");

}

public void sayGoodBye() {//无参方法

System.out.println(name + ":使用sayGoodBye方法");

}

public void say(String info) {//有参方法

System.out.println(name + ":" + info);

}

public void say(String info, int sum) {//有参方法(重载say方法)

for (int i = 0; i < sum; i++) {

System.out.println(name + ":" + info);

}

}

private void privateMethod() {//私有方法

System.out.println(name + ":这是一个私有方法");

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

以上这个用于测试反射的实体类创建成功后,先学习反射中是如何获取类对象的。

反射的第一步就是要获取操作类的类对象,即一个Class的实例,JVM中每个被加载的类有且只有一个类对象与之对应,获取到这个类对象后我们就可以通QNTdPccKLb过这个类对象来了解该类的一切信息(类名、有哪些方法、属性等等) 以便在程序运行期间通过反射机制进行相关操作

这里介绍三种获取类对象的方式:

(包名.)类名.class

Class personClass = reflect_text.Person.class;

Class intClass = int.class;

这种方式最直接,但是由于是靠硬编码形式写死(编译期间已经确定),因此不够灵活。但是需要注意,基本类型(int\double等)只能通过这种方式获取类对象

Class.forName(String className)

Class personClass = Class.forName("reflect_text.Person");

Class stringClass = Class.forName("java.lang.String");

这种方式较为常用,遵循运行期绑定。

类加载器ClassLoader

Class stringClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.String");

Class personClass = ClassLoader.getSystemClassLoader().loadClass("reflect_text.Person");

在这一节中介绍几个简单的方法:

getName()

获取类的完全限定名:包名.类名

getSimpleName()

仅仅获取类名

getMethods()

返回一个Method数组,获取class所表示的类的所有公开方法(包含从超类中继承的方法)

例子:

Scanner scanner = new Scanner(System.in);

Class cls = Class.forName(scanner.nextLine());//运行期绑定

String name = cls.getName();//获取类的完全限定名:包名.类名

System.out.println("完全限定名 = " + name);

name = cls.getSimpleName();//仅获取类名

System.out.println("仅类名 = " + name);

Method[] methods = cls.getMethods();

for (Method m : methods) {

System.out.print(m.getName()+"\t");

}

4、反射->利用无参构造实例化对象

Class类中提供了一个方法newInstance()来实例化,该方法要求此类必须具有无参构造器,它是通过无参构造器实例化对象的。

Person person = new Person();

//1获取要实例化的类的类对象

Scanner scanner = new Scanner(System.in);

System.out.println("请输入类名:");

Class cls = Class.forName(scanner.nextLine());

/*

通过Class提供的方法newInstance()来实例化

该方法要求此类必须具有无参构造器,它是通过无参构造器实例化对象的

*/

Object obj = cls.newInstance();

System.out.println("obj = " + obj);

5、反射->利用有参构造实例化对象

getConstructor()

//获取无参构造器,可以利用无参构造器实例化对象,但这个方法对于使用无参构造器实例化对象可有可无

getConstructor(类对象)

//通过类对象获取特定的构造器,该参数列表是根据特定构造器的参数列表类型来决定的,如

getConstructor(String.class, int.class)

即为调用Person类中两个参数的有参构造器

public Person(String name, int age) {//有参构造

this.name = name;

this.age = age;

}

举例

//加载类对象

Class cls = Class.forName("reflect.Person");

//通过类对象获取特定的构造器

Constructor c = cls.getConstructor(String.class, int.class);

Object o = c.newInstance("流年", 21);//实例化

System.out.println(o);

结果可知初始值已经被修改

6、反射->调用无参方法

getMethod(String MethodName)

获取类对象的MethodName方法,返回值类型为Method

invoke(Object object)

执行object对象的某方法

举例

//一般调用方法的做法-------------------

Person p = new Person();//实例化对象

p.sayHello();//调用该对象方法

//反射机制调用方法-----------------------

//1、实例化对象

Class cls = Class.forName("reflect_text.Person");

Object o = cls.newInstance();

//2、调用o的sayHello方案

//2.1通过Class获取Person的sayHello方法

Method method = cls.getMethod("sayHello");

//2.2调用o的该方法

method.invoke(o);//等效于一般方法中的o.sayHello()

可见两种操作均能达到一样的效果

7、反射->调用有参方法

getMethod(String MethodName, 类对象)

获取类对象的MethodName有参方法,并传入对应参数类型的类对象,返回值类型为Method

举例

//一般调用有参方法------------------------

Person p = new Person();

p.say("七夕快乐~");

p.say("七夕快乐~",3);

//反射机制调用有参方法---------------------

Class cls = Class.forName("reflect_text.Person");

Object o = cls.newInstance();

//调用say(String info)方法

Method m1 = cls.getMethod("say", String.class);

m1.invoke(o, "春节快乐~");

//调用say(String info, int sum)

Method m2 = cls.getMethod("say", String.class, ihttp://nt.class);

m2.invoke(o,"春节快乐~",3);

通过结果可以看到,效果都是一样的

8、反射->访问私有方法

注意:反射访问私有的方法,但是会破坏类的封装性

getDeclaredMethod(String MethodName)

可以仅获取此类定义的所有方法,包含私有方法

setAccessible(boolean flag)

开启私有方法的访问权限

举例

//正常情况下,在本类中不可以访问外部的私有方法

//但在反射机制中可行

Class cls = Class.forName("reflect_text.Person");

Object o = cls.newInstance();

Method method = cls.getDeclaredMethod("privateMethod");

method.setAccessible(true);//打开访问权限

method.invoke(o);

9、反射->类加载路径

加载资源时常用相对路径,之前学习的相对路径./由于运行环境不同,位置并非固定,因此实际开发中使用较少。

接下来介绍,在开发中常用的类加载路径

常用的路径通常为类的加载路径,有两个:

1:类对象.getResource()与当前类所处同一目录

2:类加载器.getResource()类加载路径,类的package定义中根包位置。

例如:有一个类:

package reflect_text;

public class WebServer{

……

}

在WebServer类中,当我们使用上述两种方式获取路径时他们的对应位置为:

WebServer.class.getResource()

当前WebServer所在的目录(编译后的class文件所在目录)

WebServer.class.getClassLoader().getResource()

则是在WebServer的包的最上级,即com包的上一级

package reflect_text;

public class ReflectDemo {

File dir = new File(ReflectDemo.class.getResource(".").toURI());

System.out.println("dir = " + dir);

//dir = D:\ClassCode\JavaSE_API\out\production\JavaSE_API\reflect

File dir2 = new File(ReflectDemo.class.getClassLoader().getResource(".").toURI());

System.out.println("dir2 = " + dir2);

//dir2 = D:\ClassCode\JavaSE_API\out\production\JavaSE_API

}

总结

本片文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:网络安全中等保是什么?为什么要进行等保测评?
下一篇:开源deskvideosys办公行为管理代理端代码解读
相关文章

 发表评论

评论列表