加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java 反射(Reflection)-干货

发布时间:2020-12-14 06:32:06 所属栏目:Java 来源:网络整理
导读:看了很多关于java 反射的文章,自己把所看到的总结一下。对自己,对他人或多或少有帮助吧。 首先来看看 Oracle里面对Reflection的描述: Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of

看了很多关于java 反射的文章,自己把所看到的总结一下。对自己,对他人或多或少有帮助吧。

首先来看看Oracle里面对Reflection的描述:

Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind,reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

简单的讲:

  • 反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们。

再简单一点的讲:

  • 我们可以在获得程序或程序集中每一个类型的成员和成员的信息。

举个例子:

Java是面向对象语言,我们可以把老虎,狮子等具有相同性质的动物归类(抽象)为猫科动物,他们具有牙齿,胡须等一些属性。同时具有吃肉()的动作。

同样的道理,我们所接触到的类Class,也可以把他们抽象出来,有类名,成员变量,方法等。

那么既然能够把类看做是对象,那么java就可以对其进行处理。

  • Java反射(Reflection)框架主要提供以下功能:

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时构造任意一个类的对象;
  3. 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  4. 在运行时调用任意一个对象的方法
  • Java反射(Reflection)的主要用途

  1. 工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了
  2. 数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动
  3. 分析类文件:毕竟能得到类中的方法等等
  4. 访问一些不能访问的变量或属性:破解别人代码
  • Java反射(Reflection)的基本运用

  获取Class有一下三种方法:

1. 使用Class类的forName静态方法

Class.forName("com.mysql.jdbc.Driver" }

2. 直接获取某一个对象的class

Class klass = . Class classInt = Integer.TYPE;

3. 调用某个对象的getClass()方法

Demo demo= }

?下面是一个完整的Demo展示Java Reflection的操作:

main(String[] args) System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" System.out.println("===============================================" Person person = System.out.println("Demo1: 包名: " + person.getClass().getPackage().getName() + "," + "完整类名: " + Demo2() Class class1 = Class class2 = class1 = Class.forName("com.b510.hongten.test.reflex.Person" System.out.println("Demo2:(写法1) 包名: " + class1.getPackage().getName() + "," + "完整类名: " + class2 = Person. System.out.println("Demo2:(写法2) 包名: " + class2.getPackage().getName() + "," + "完整类名: " + Demo3() Class class1 = class1 = Class.forName("com.b510.hongten.test.reflex.Person" Person person = person.setAge(20 person.setName("Hongten" System.out.println("Demo3: " + person.getName() + " : " + Demo4() Class class1 = Person person1 = Person person2 = class1 = Class.forName("com.b510.hongten.test.reflex.Person" Constructor[] constructors = person1 = (Person) constructors[0 person1.setAge(30 person1.setName("Hongten" person2 = (Person) constructors[1].newInstance(20,"Hongten" System.out.println("Demo4: " + person1.getName() + " : " + person1.getAge() + "," + person2.getName() + " : " + Demo5() Class class1 = class1 = Class.forName("com.b510.hongten.test.reflex.Person" Object obj = Field personNameField = class1.getDeclaredField("name" personNameField.setAccessible( personNameField.set(obj,"HONGTEN" System.out.println("Demo5: 修改属性之后得到属性变量的值:" + Demo6() Class class1 = class1 = Class.forName("com.b510.hongten.test.reflex.SuperMan" Class superClass = System.out.println("Demo6: SuperMan类的父类名: " + System.out.println("===============================================" Field[] fields = ( i = 0; i < fields.length; i++ System.out.println("类中的成员: " + System.out.println("===============================================" Method[] methods = ( i = 0; i < methods.length; i++ System.out.println("Demo6,取得SuperMan类的方法:" System.out.println("函数名:" + System.out.println("函数返回类型:" + System.out.println("函数访问修饰符:" + System.out.println("函数代码写法: " + System.out.println("===============================================" Class interfaces[] = ( i = 0; i < interfaces.length; i++ System.out.println("实现的接口类名: " + Demo7() Class class1 = class1 = Class.forName("com.b510.hongten.test.reflex.SuperMan" System.out.println("Demo7: n调用无参方法fly()" Method method = class1.getMethod("fly" System.out.println("调用有参方法walk(int m)" method = class1.getMethod("walk",. method.invoke(class1.newInstance(),100 Demo8() Class class1 = class1 = Class.forName("com.b510.hongten.test.reflex.SuperMan" String nameString = System.out.println("Demo8: 类加载器类名: " + Person( .age = .name = setAge( .age = .name = SuperMan Person System.out.println("fly method...." setBlueBriefs( BlueBriefs = walk( System.out.println("fly in " + m + " m" walk( }
  • ?说说工厂模式和Java 反射(Reflection)机制

?如果在工厂模式下面,我们不使用Java 反射(Reflection)机制,会是什么样子呢?

Cats cats = FactoryTest.getInstance("Tiger" Cats cats = ("Tiger" cats = ("Lion" cats = Tiger System.out.println("The tiger eat meat." Lion System.out.println("The lion eat meat." }

我们会发现:

当我们在添加一个子类(Puma-美洲狮)的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。

我们对程序进行修改,加入反射机制。

Cats cats = FactoryTest.getInstance("com.b510.hongten.test.reflex.Tiger" Cats cats = cats = } } } Tiger System.out.println("The tiger eat meat." Lion System.out.println("The lion eat meat." }

我们会发现利用了Java Reflection以后,现在就算我们添加任意多个子类的时候,工厂类就不需要修改。我们只需要传递工厂类的实现类的名称即可。

然而,在这样的情况下面,如果我们需要运行Lion实例的时候,我们还需要去修改java代码。

Cats cats = FactoryTest.getInstance("com.b510.hongten.test.reflex.Lion");

上面的代码虽然可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。

能不能不需要修改java代码,同样可以完成相同的操作呢?是可以的。

我们可以让工厂模式结合属性文件(如:*.properties,*.xml文件)

?属性文件:/reflex/cats.properties

tiger=com.b510.hongten.test.reflex.Tiger

测试文件:/reflex/FactoryTest.java

cats = FactoryTest.getInstance(getPro().getProperty("tiger" (cats != } } Cats cats = cats = } } } Properties getPro() Properties pro = File f = File("cats.properties" pro.load( } pro.setProperty("lion","com.b510.hongten.test.reflex.Lion" pro.setProperty("tiger","com.b510.hongten.test.reflex.Tiger" pro.store( FileOutputStream(f),"FRUIT CLASS" Tiger System.out.println("The tiger eat meat." Lion System.out.println("The lion eat meat." }

作为开发者,我们只需要配置cats.properties属性文件即可。极大的提高了程序的扩展性能。

  • Java反射(Reflection)的一些注意事项

  1. 由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。
  2. 另外,反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

========================================================

More reading,and english is important.

I'm Hongten

大哥哥大姐姐,觉得有用打赏点哦!多多少少没关系,一分也是对我的支持和鼓励。谢谢。Hongten博客排名在100名以内。粉丝过千。Hongten出品,必是精品。

E | hongtenzone@foxmail.com ?B |?

========================================================

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读