很多时候我们会遇到别人问一个问题:你给我讲一下反射,到底是什么东西?怎么实现的?我们能用反射来做什么?它有什么优缺点?下面我们会围绕着这几个问题展开:

一、反射机制是什么?

反射是什么?什么是反?什么是正射?

有反就有正,我们知道正常情况, 如果我们希望创建一个对象,会使用以下的语句:

  1. Person person = new Person();

其实我们第一次执行上面的语句的时候,JVM会先加载Person.class,加载到内存完之后,在方法区/堆中会创建了一个Class对象,对应这个Person类。这里有争议,有人说是在方法区,有些人说是在堆。个人感觉应该JVM规范说是在方法区,但是不是强制要求,而且不同版本的JVM实现也不一样。具体参考以下链接,这里不做解释:

https://www.cnblogs.com/xy-nb/p/6773051.html

而上面正常的初始化对象的方法,也可以说是“正射”,就是使用Class对象创建出一个Person对象。

而反射则相反,是根据Person对象,获取到Class对象,然后可以获取到Person类的相关信息,进行初始化或者调用等一系列操作。

运行状态时,可以构造任何一个类的对象,获取到任意一个对象所属的类信息,以及这个类的成员变量或者方法,可以调用任意一个对象的属性或者方法。可以理解为具备了 动态加载对象 以及 对对象的基本信息进行剖析和使用 的能力。

提供的功能包括:

  • 1.在运行时判断一个对象所属的类
  • 2.在运行时构造任意一个类的对象
  • 3.在运行时获取一个类定义的成员变量以及方法
  • 4.在运行时调用任意一个对象的方法
  • 5.生成动态代理

灵活,强大,可以在运行时装配,无需在组件之间进行源代码链接,但是使用不当效率会有影响。所有类的对象都是Class的实例。

既然我们可以对类的全限定名,方法以及参数等进行配置,完成对象的初始化,那就是相当于增加了java的可配置性。

这里特别需要明确的一点:类本身也是一个对象,方法也是一个对象,在Java里面万物皆可对象,除了基础数据类型...

二、反射的具体使用

2.1 获取对象的包名以及类名

  1. package invocation;
  2. public class MyInvocation {
  3. public static void main(String[] args) {
  4. getClassNameTest();
  5. }
  6. public static void getClassNameTest(){
  7. MyInvocation myInvocation = new MyInvocation();
  8. System.out.println("class: " + myInvocation.getClass());
  9. System.out.println("simpleName: " + myInvocation.getClass().getSimpleName());
  10. System.out.println("name: " + myInvocation.getClass().getName());
  11. System.out.println("package: " +
  12. "" + myInvocation.getClass().getPackage());
  13. }
  14. }

运行结果:

  1. class: class invocation.MyInvocation
  2. simpleName: MyInvocation
  3. name: invocation.MyInvocation
  4. package: package invocation

由上面结果我们可以看到:

1.getClass():打印会带着class+全类名

2.getClass().getSimpleName():只会打印出类名

3.getName():会打印全类名

4.getClass().getPackage():打印出package+包名

getClass()获取到的是一个对象,getPackage()也是。

2.2 获取Class对象

在java中,一切皆对象。java中可以分为两种对象,实例对象和Class对象。这里我们说的获取Class对象,其实就是第二种,Class对象代表的是每个类在运行时的类型信息,指和类相关的信息。比如有一个Student类,我们用Student student = new Student()new一个对象出来,这个时候Student这个类的信息其实就是存放在一个对象中,这个对象就是Class类的对象,而student这个实例对象也会和Class对象关联起来。

我们有三种方式可以获取一个类在运行时的Class对象,分别是

  • Class.forName("com.Student")
  • student.getClass()
  • Student.class

实例代码如下:

  1. package invocation;
  2. public class MyInvocation {
  3. public static void main(String[] args) {
  4. getClassTest();
  5. }
  6. public static void getClassTest(){
  7. Class<?> invocation1 = null;
  8. Class<?> invocation2 = null;
  9. Class<?> invocation3 = null;
  10. try {
  11. // 最常用的方法
  12. invocation1 = Class.forName("invocation.MyInvocation");
  13. }catch (Exception ex){
  14. ex.printStackTrace();
  15. }
  16. invocation2 = new MyInvocation().getClass();
  17. invocation3 = MyInvocation.class;
  18. System.out.println(invocation1);
  19. System.out.println(invocation2);
  20. System.out.println(invocation3);
  21. }
  22. }

执行的结果如下,三个结果一样:

  1. class invocation.MyInvocation
  2. class invocation.MyInvocation
  3. class invocation.MyInvocation

2.3 getInstance()获取指定类型的实例化对象

首先我们有一个Student类,后面都会沿用这个类,将不再重复。

  1. class Student{
  2. private int age;
  3. private String name;
  4. public Student() {
  5. }
  6. public Student(int age) {
  7. this.age = age;
  8. }
  9. public Student(String name) {
  10. this.name = name;
  11. }
  12. public Student(int age, String name) {
  13. this.age = age;
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. public String getName() {
  23. return name;
  24. }
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28. @Override
  29. public String toString() {
  30. return "Student{" +
  31. "age=" + age +
  32. ", name='" + name + '\'' +
  33. '}';
  34. }

我们可以使用getInstance()方法构造出一个Student的对象:

  1. public static void getInstanceTest() {
  2. try {
  3. Class<?> stduentInvocation = Class.forName("invocation.Student");
  4. Student student = (Student) stduentInvocation.newInstance();
  5. student.setAge(9);
  6. student.setName("Hahs");
  7. System.out.println(student);
  8. }catch (Exception ex){
  9. ex.printStackTrace();
  10. }
  11. }
  12. 输出结果如下:
  13. Student{age=9, name='Hahs'}

但是如果我们取消不写Student的无参构造方法呢?就会出现下面的报错:

  1. java.lang.InstantiationException: invocation.Student
  2. at java.lang.Class.newInstance(Class.java:427)
  3. at invocation.MyInvocation.getInstanceTest(MyInvocation.java:40)
  4. at invocation.MyInvocation.main(MyInvocation.java:8)
  5. Caused by: java.lang.NoSuchMethodException: invocation.Student.<init>()
  6. at java.lang.Class.getConstructor0(Class.java:3082)
  7. at java.lang.Class.newInstance(Class.java:412)
  8. ... 2 more

这是因为我们重写了构造方法,而且是有参构造方法,如果不写构造方法,那么每个类都会默认有无参构造方法,重写了就不会有无参构造方法了,所以我们调用newInstance()的时候,会报没有这个方法的错误。值得注意的是,newInstance()是一个无参构造方法。

2.4 通过构造函数对象实例化对象

除了newInstance()方法之外,其实我们还可以通过构造函数对象获取实例化对象,怎么理解?这里只构造函数对象,而不是构造函数,也就是构造函数其实就是一个对象,我们先获取构造函数对象,当然也可以使用来实例化对象。

可以先获取一个类的所有的构造方法,然后遍历输出:

  1. public static void testConstruct(){
  2. try {
  3. Class<?> stduentInvocation = Class.forName("invocation.Student");
  4. Constructor<?> cons[] = stduentInvocation.getConstructors();
  5. for(int i=0;i<cons.length;i++){
  6. System.out.println(cons[i]);
  7. }
  8. }catch (Exception ex){
  9. ex.printStackTrace();
  10. }
  11. }

输出结果:

  1. public invocation.Student(int,java.lang.String)
  2. public invocation.Student(java.lang.String)
  3. public invocation.Student(int)
  4. public invocation.Student()

取出一个构造函数我们可以获取到它的各种信息,包括参数,参数个数,类型等等:

  1. public static void constructGetInstance() {
  2. try {
  3. Class<?> stduentInvocation = Class.forName("invocation.Student");
  4. Constructor<?> cons[] = stduentInvocation.getConstructors();
  5. Constructor constructors = cons[0];
  6. System.out.println("name: " + constructors.getName());
  7. System.out.println("modifier: " + constructors.getModifiers());
  8. System.out.println("parameterCount: " + constructors.getParameterCount());
  9. System.out.println("构造参数类型如下:");
  10. for (int i = 0; i < constructors.getParameterTypes().length; i++) {
  11. System.out.println(constructors.getParameterTypes()[i].getName());
  12. }
  13. } catch (Exception ex) {
  14. ex.printStackTrace();
  15. }
  16. }

输出结果,modifier是权限修饰符,1表示为public,我们可以知道获取到的构造函数是两个参数的,第一个是int,第二个是String类型,看来获取出来的顺序并不一定是我们书写代码的顺序。

  1. name: invocation.Student
  2. modifier: 1
  3. parameterCount: 2
  4. 构造参数类型如下:
  5. int
  6. java.lang.String

既然我们可以获取到构造方法这个对象了,那么我们可不可以通过它去构造一个对象呢?答案肯定是可以!!!

下面我们用不同的构造函数来创建对象:

  1. public static void constructGetInstanceTest() {
  2. try {
  3. Class<?> stduentInvocation = Class.forName("invocation.Student");
  4. Constructor<?> cons[] = stduentInvocation.getConstructors();
  5. // 一共定义了4个构造器
  6. Student student1 = (Student) cons[0].newInstance(9,"Sam");
  7. Student student2 = (Student) cons[1].newInstance("Sam");
  8. Student student3 = (Student) cons[2].newInstance(9);
  9. Student student4 = (Student) cons[3].newInstance();
  10. System.out.println(student1);
  11. System.out.println(student2);
  12. System.out.println(student3);
  13. System.out.println(student4);
  14. } catch (Exception ex) {
  15. ex.printStackTrace();
  16. }

输出如下:

  1. Student{age=9, name='Sam'}
  2. Student{age=0, name='Sam'}
  3. Student{age=9, name='null'}
  4. Student{age=0, name='null'}

构造器的顺序我们是必须一一针对的,要不会报一下的参数不匹配的错误:

  1. java.lang.IllegalArgumentException: argument type mismatch
  2. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
  3. at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
  4. at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
  5. at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
  6. at invocation.MyInvocation.constructGetInstanceTest(MyInvocation.java:85)
  7. at invocation.MyInvocation.main(MyInvocation.java:8)

2.5 获取类继承的接口

通过反射我们可以获取接口的方法,如果我们知道某个类实现了接口的方法,同样可以做到通过类名创建对象调用到接口的方法。

首先我们定义两个接口,一个InSchool:

  1. public interface InSchool {
  2. public void attendClasses();
  3. }

一个AtHome:

  1. public interface AtHome {
  2. public void doHomeWork();
  3. }

创建一个实现两个接口的类Student.java

  1. public class Student implements AtHome, InSchool {
  2. public void doHomeWork() {
  3. System.out.println("I am a student,I am doing homework at home");
  4. }
  5. public void attendClasses() {
  6. System.out.println("I am a student,I am attend class in school");
  7. }
  8. }

测试代码如下:

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> studentClass = Class.forName("invocation.Student");
  4. Class<?>[] interfaces = studentClass.getInterfaces();
  5. for (Class c : interfaces) {
  6. // 获取接口
  7. System.out.println(c);
  8. // 获取接口里面的方法
  9. Method[] methods = c.getMethods();
  10. // 遍历接口的方法
  11. for (Method method : methods) {
  12. // 通过反射创建对象
  13. Student student = (Student) studentClass.newInstance();
  14. // 通过反射调用方法
  15. method.invoke(student, null);
  16. }
  17. }
  18. }
  19. }

结果如下:

可以看出其实我们可以获取到接口的数组,并且里面的顺序是我们继承的顺序,通过接口的Class对象,我们可以获取到接口的方法,然后通过方法反射调用实现类的方法,因为这是一个无参数的方法,所以只需要传null即可。

2.6 获取父类相关信息

主要是使用getSuperclass()方法获取父类,当然也可以获取父类的方法,执行父类的方法,首先创建一个Animal.java:

  1. public class Animal {
  2. public void doSomething(){
  3. System.out.println("animal do something");
  4. }
  5. }

Dog.java继承于Animal.java

  1. public class Dog extends Animal{
  2. public void doSomething(){
  3. System.out.println("Dog do something");
  4. }
  5. }

我们可以通过反射创建Dog对象,获取其父类Animal以及创建对象,当然也可以获取Animal的默认父类Object

  1. public class Test {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> dogClass = Class.forName("invocation02.Dog");
  4. System.out.println(dogClass);
  5. invoke(dogClass);
  6. Class<?> animalClass = dogClass.getSuperclass();
  7. System.out.println(animalClass);
  8. invoke(animalClass);
  9. Class<?> objectClass = animalClass.getSuperclass();
  10. System.out.println(objectClass);
  11. invoke(objectClass);
  12. }
  13. public static void invoke(Class<?> myClass) throws Exception {
  14. Method[] methods = myClass.getMethods();
  15. // 遍历接口的方法
  16. for (Method method : methods) {
  17. if (method.getName().equalsIgnoreCase("doSomething")) {
  18. // 通过反射调用方法
  19. method.invoke(myClass.newInstance(), null);
  20. }
  21. }
  22. }
  23. }

输入如下:

2.7 获取当前类的公有属性和私有属性以及更新

创建一个Person.java,里面有静态变量,非静态变量,以及publicprotected,private不同修饰的属性。

  1. public class Person {
  2. public static String type ;
  3. private static String subType ;
  4. // 名字(公开)
  5. public String name;
  6. protected String gender;
  7. private String address;
  8. @Override
  9. public String toString() {
  10. return "Person{" +
  11. "name='" + name + '\'' +
  12. ", address='" + address + '\'' +
  13. '}';
  14. }
  15. }

使用getFields()可以获取到public的属性,包括static属性,使用getDeclaredFields()可以获取所有声明的属性,不管是publicprotected,private不同修饰的属性。

修改public属性,只需要field.set(object,value)即可,但是private属性不能直接set,否则会报以下的错误。

  1. Exception in thread "main" java.lang.IllegalAccessException: Class invocation03.Tests can not access a member of class invocation03.Person with modifiers "private"
  2. at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
  3. at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
  4. at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
  5. at java.lang.reflect.Field.set(Field.java:761)
  6. at invocation03.Tests.main(Tests.java:21)

那么需要怎么做呢?private默认是不允许外界操作其值的,这里我们可以使用field.setAccessible(true);,相当于打开了操作的权限。

那static的属性修改和非static的一样,但是我们怎么获取呢?

如果是public修饰的,可以直接用类名获取到,如果是private修饰的,那么需要使用filed.get(object),这个方法其实对上面说的所有的属性都可以的。

测试代码如下

  1. public class Tests {
  2. public static void main(String[] args) throws Exception{
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Field[] fields = personClass.getFields();
  5. // 获取公开的属性
  6. for(Field field:fields){
  7. System.out.println(field);
  8. }
  9. System.out.println("=================");
  10. // 获取所有声明的属性
  11. Field[] declaredFields = personClass.getDeclaredFields();
  12. for(Field field:declaredFields){
  13. System.out.println(field);
  14. }
  15. System.out.println("=================");
  16. Person person = (Person) personClass.newInstance();
  17. person.name = "Sam";
  18. System.out.println(person);
  19. // 修改public属性
  20. Field fieldName = personClass.getDeclaredField("name");
  21. fieldName.set(person,"Jone");
  22. // 修改private属性
  23. Field addressName = personClass.getDeclaredField("address");
  24. // 需要修改权限
  25. addressName.setAccessible(true);
  26. addressName.set(person,"东风路47号");
  27. System.out.println(person);
  28. // 修改static 静态public属性
  29. Field typeName = personClass.getDeclaredField("type");
  30. typeName.set(person,"人类");
  31. System.out.println(Person.type);
  32. // 修改静态 private属性
  33. Field subType = personClass.getDeclaredField("subType");
  34. subType.setAccessible(true);
  35. subType.set(person,"黄种人");
  36. System.out.println(subType.get(person));
  37. }
  38. }

结果:

从结果可以看出,不管是public,还是protectedprivate修饰的,我们都可以通过反射对其进行查询和修改,不管是静态变量还是非静态变量。

getDeclaredField()可以获取到所有声明的属性,而getFields()则只能获取到public的属性。对于非public的属性,我们需要修改其权限才能访问和修改:field.setAccessible(true)

获取属性值需要使用field.get(object),值得注意的是:每个属性,其本身就是对象

2.8 获取以及调用类的公有/私有方法

既然可以获取到公有属性和私有属性,那么我想,执行公有方法和私有方法应该都不是什么问题?

那下面我们一起来学习一下...

先定义一个类,包含各种修饰符,以及是否包含参数,是否为静态方法,Person.java:

  1. public class Person {
  2. // 非静态公有无参数
  3. public void read(){
  4. System.out.println("reading...");
  5. }
  6. // 非静态公有无参数有返回
  7. public String getName(){
  8. return "Sam";
  9. }
  10. // 非静态公有带参数
  11. public int readABookPercent(String name){
  12. System.out.println("read "+name);
  13. return 80;
  14. }
  15. // 私有有返回值
  16. private String getAddress(){
  17. return "东方路";
  18. }
  19. // 公有静态无参数无返回值
  20. public static void staticMethod(){
  21. System.out.println("static public method");
  22. }
  23. // 公有静态有参数
  24. public static void staticMethodWithArgs(String args){
  25. System.out.println("static public method:"+args);
  26. }
  27. // 私有静态方法
  28. private static void staticPrivateMethod(){
  29. System.out.println("static private method");
  30. }
  31. }

首先我们来看看获取里面所有的方法:

  1. public class Tests {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Method[] methods = personClass.getMethods();
  5. for (Method method : methods) {
  6. System.out.println(method);
  7. }
  8. System.out.println("=============================================");
  9. Method[] declaredMethods = personClass.getDeclaredMethods();
  10. for (Method method : declaredMethods) {
  11. System.out.println(method);
  12. }
  13. }
  14. }

结果如下:



咦,我们发现getMethods()确实可以获取所有的公有的方法,但是有一个问题,就是他会把父类的也获取到,也就是上面图片绿色框里面的,我们知道所有的类默认都继承了Object类,所以它把Object的那些方法都获取到了。

getDeclaredMethods确实可以获取到公有和私有的方法,不管是静态还是非静态,但是它是获取不到父类的方法的。

那如果我们想调用方法呢?先试试调用非静态方法:

  1. public class Tests {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Person person = (Person) personClass.newInstance();
  5. Method[] declaredMethods = personClass.getDeclaredMethods();
  6. for (Method method : declaredMethods) {
  7. if(method.getName().equalsIgnoreCase("read")){
  8. method.invoke(person,null);
  9. System.out.println("===================");
  10. }else if(method.getName().equalsIgnoreCase("getName")){
  11. System.out.println(method.invoke(person,null));
  12. System.out.println("===================");
  13. }else if(method.getName().equalsIgnoreCase("readABookPercent")){
  14. System.out.println(method.invoke(person,"Sam"));
  15. System.out.println("===================");
  16. }
  17. }
  18. }
  19. }

结果如下,可以看出method.invoke(person,null);是调用无参数的方法,而method.invoke(person,"Sam")则是调用有参数的方法,要是有更多参数,也只需要在里面多加一个参数即可,返回值也同样可以获取到。

那么private方法呢?我们照着来试试,试试就试试,who 怕 who?

  1. public class Tests {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Person person = (Person) personClass.newInstance();
  5. Method[] declaredMethods = personClass.getDeclaredMethods();
  6. for (Method method : declaredMethods) {
  7. if(method.getName().equalsIgnoreCase("getAddress")){
  8. method.invoke(person,null);
  9. }
  10. }
  11. }
  12. }

结果报错了:

  1. Exception in thread "main" java.lang.IllegalAccessException: Class invocation03.Tests can not access a member of class invocation03.Person with modifiers "private"
  2. at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
  3. at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
  4. at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
  5. at java.lang.reflect.Method.invoke(Method.java:491)
  6. at invocation03.Tests.main(Tests.java:13)

一看就是没有权限,小场面,不要慌,我来操作一波,只要加上

  1. method.setAccessible(true);

哦豁,完美解决了...

那么问题来了,上面说的都是非静态的,我就想要调用静态的方法。

当然用上面的方法,对象也可以直接调用到类的方法的:

一点问题都没有,为什么输出结果有几个null,那是因为这函数是无返回值的呀,笨蛋...

如果我不想用遍历方法的方式,再去判断怎么办?能不能直接获取到我想要的方法啊?那答案肯定是可以啊。

  1. public class Tests {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Person person = (Person) personClass.newInstance();
  5. Method method = personClass.getMethod("readABookPercent", String.class);
  6. method.invoke(person, "唐诗三百首");
  7. }
  8. }

结果和上面调用的完全一样,图我就不放了,就一行字。要是这个方法没有参数呢?那就给一个null就可以啦。或者不给也可以。

  1. public class Tests {
  2. public static void main(String[] args) throws Exception {
  3. Class<?> personClass = Class.forName("invocation03.Person");
  4. Person person = (Person) personClass.newInstance();
  5. Method method = personClass.getMethod("getName",null);
  6. System.out.println(method.invoke(person));
  7. }
  8. }

三、反射的优缺点

3.1 优点

反射可以在不知道会运行哪一个类的情况下,获取到类的信息,创建对象以及操作对象。这其实很方便于拓展,所以反射会是框架设计的灵魂,因为框架在设计的时候,为了降低耦合度,肯定是需要考虑拓展等功能的,不能将类型写死,硬编码。

降低耦合度,变得很灵活,在运行时去确定类型,绑定对象,体现了多态功能。

3.2 缺点

这么好用,没有缺点?怎么可能!!!有利就有弊,事物都是有双面性的。

即使功能很强大,但是反射是需要动态类型的,JVM没有办法优化这部分代码,执行效率相对直接初始化对象较低。一般业务代码不建议使用。

反射可以修改权限,比如上面访问到private这些方法和属性,这是会破坏封装性的,有安全隐患,有时候,还会破坏单例的设计。

反射会使代码变得复杂,不容易维护,毕竟代码还是要先写给人看的嘛,逃~

此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~

技术之路不在一时,山高水长,纵使缓慢,驰而不息。

Java反射说得透彻一些的更多相关文章

  1. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  4. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

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

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

随机推荐

  1. 阿里P6晋升到P7是一个坎吗? P7 晋升总结

    作者:程序之心丁仪 来源:https://chengxuzhixin.com/blog/post/P6_jin_sheng_dao_P7_zong_jie.html 公众号停更了挺长一段时间,首先说声 ...

  2. Python+Selenium(1)- 环境搭建

    一,Selenium 简介 Selenium是目前最流行的web自动化测试工具,也常用于网络爬虫,已经更新到3以上的版本. 1,组件 它提供了以下web自动化测试组件: Selenium IDE,Fi ...

  3. VC中句柄、指针、ID之间的转换

    win32直接操作的是句柄HANDLE,每个句柄就对应windows窗口,而vc对HANDLE进行类封装,间接操作的都是HANDLE,现在句柄只是类的一个成员变量. 从句柄到指针 CWnd* pWnd ...

  4. 聊一聊C#基本类型

    C#基本类型 闲来无事,重新温习了下C#基本类型.以下讲的基本类型主要是包括基本的值类型类型和string.struct和class不包含其中. C#基本类型------值类型: bool,byte, ...

  5. 【Kata Daily 190908】How Much?

    原题: I always thought that my old friend John was rather richer than he looked, but I never knew exac ...

  6. 测试php

    /** * 测试guzzle * * @return void */ public function index() { $client = new GuzzleHttp\Client(); //12 ...

  7. iframe框架下的某一页面跳转到另外一个页面

    //iframe只在当前页跳转 window.location = "/Admin/Blog/Index"; 只在当前页跳转 而不是整个页面都跳转

  8. 内网渗透 day12-免杀框架2

    免杀框架2 目录 1. IPC管道连接 2. 查看wifi密码 3. Phantom-Evasion免杀框架的运用 4. 自解压(sfx) 5. 数字签名 6. 资源替换 1. IPC管道连接 命名管 ...

  9. python_面向对象_组合

    组合: 一个类的对象是另外一个类对象的属性 # 组合 # 一个类的对象是另一个类对象的属性 # 什么时候使用组合:当两个类之间的关系是 :什么有什么的关系 : 班级有学生 学生有班级 班级有课程 图书 ...

  10. 程序员注意【自verycd.com的JavaAmg77 】

    展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告 走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的1 ...