Java 高级开发必修知识---反射

 

1.在java语言中,静态的成员变量,普通数据类型类等等都是对象,类也是对象,是java.lang.Class类的实例对象,任何一个类都是Class的实例对象,称为这个类的类类型,这个实例对象有三种表达方式

程序猿们经常说的一句话:反射反射。。。程序员的快乐

(1)Class c1=类名.class  任何一个类都有一个隐含的静态成员变量class

 

(2)Class c2=类的实例.getClass()  知道该类的实例对象后用getClass()方法获取

 

(3)Class c3=null;

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

c3=Class.forName("类的全称");

对于任意一个对象,都能够调用它的任意一个方法和属性;

c1=c2=c3,都代表了这个类的类类型,一个类只可能是Class类的一个实例对象,无论用哪种方法获取的都是同一个,我们可以通过类的类类型来创建对象实例,比如:

这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Foo foo=(Foo)c1.newInstance() 得出来的结果进行强制类型转换就可以得到对象实例,但前提是Foo类必须要有无参构造方法

 

2.加载类

文章开始之前 提一下:

(1)c3=Class.forName("类的全称")不仅仅代表了类的类类型,还代表了动态加载类,编译时刻加载类是静态加载类,运行时刻是动态加载类

java反射操作其实就是主要围绕Class,Field,Methon,Constructor等几个类来操作其中的方法

(2)new创建类是静态加载类,在编译时刻就需要加载所有的可能用到的类,所以任何一个类出现问题都无法编译成功

 

(3)动态加载类在运行时加载,可能用到的类出错在编译时不会报错,只有在用到时才会报错,但所有可能用到的类必须继承同一个接口才能方便调用

万物皆对象。但基本数据类型 和 使用static修饰的成员不是对象

图片 1

但基本数据类型的封装类是对象

图片 2

图片 3

图片 4

 

图片 5

Class类的使用

1) 在面向对象的世界里,万事万物皆对象

A. Java语言中,普通数据类型,静态成员不是对象,其他皆对象

B. 每一个类也是对象

C. 类是java.lang.Class类的实例对象

There is a class named Class

对象的表示:

普通类对象表示:

Foo foo = new Foo();

Class类实例对象表示:

//Foo也是一个实例对象,是Class类的实例对象

任何一个类都是Class的实例对象,这个实例对象有三种表达方式

1. 任何一个类都有一个隐含的静态成员变量class:

Class c1 = Foo.class;

2. 已经指定该类的对象通过getClass方法

Foo foo = new Foo();

Class c2 = foo.getClass();

官网:c1/c2 表示了Foo类的类类型(class type)

一个类,本身就是一个对象,它是Class类的对象

万事万物皆对象,类也是对象,是Class类的实例对象,这个对象我们称为该类的类类型

3. ForName(“类的全称”);

Class c3 = null;

c3=Class.forName(“包名 .某类名”);

不管是那种表达方式,都是Class类的对象,都是Foo类的类类型。所以:

C1=c2=c3

完全可以通过类的类类型创建该类的对象(创建Foo的实例对象,但要做强制类型转换,向下转型)

前提要求:需要有无参数的构造方法

Comont comont = new Comont();
Class c1 = comont.getClass();
Class c2 = Comont.class;
try {
Comont c = (Comont) c2.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(c1 == c2);
comont.start();

 

 

3.基本的数据类型,void关键字也有类类型

动态加载类

Class.forName(“类的全称”);

1. 不仅表示了类的类类型,还代表动态加载类

2. 编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

(1) New 对象是静态加载类,在变异时刻就需要加载所有的可能使用到的类

(2) 动态加载类,在运行时刻加载

编译不会报错

运行时刻报错。找不到该类

Class c = Class.forName(arg[0]);

共同实现接口类 cc = (共同实现接口类) c.newInstance();

3. 使用记事本开发可明显区分

Java 类 要运行类:动态加载类,不需要重新编译测试类,直接运行即可

功能性的类:尽量使用动态加载

基本数据类型也有类类型

Class c1 = int.class;
Class c2 = String.class;//String类的字节码

 

数据类型和包装类的类类型不同

Void也是类

Class c3 = void.class;

 

基本数据类型

Void关键字

都存在类类型

方法也是对象,方法是Method的对象

反射:某类的字节码表示

Class c1=int.class;

获取方法信息

1. c.getName()

(1) 基本数据类型返回类型名

(2) 类返回包名 类名类的名称

2. c1.getSimpleName()

(1) 返回不带包名的类的名称

栗子:通过反射可以获取到任何类的信息

需求:打印类的信息,获取类的 成员函数

package cn.pro;

import java.lang.reflect.Method;

/**
 * 
 * @author: 房上的猫
 * 
 * @time: 下午5:34:45
 * 
 * @博客地址: https://www.cnblogs.com/lsy131479/
 *
 */

public class mymain {
    public static void printClassMessage(Object obj) {
        // 要获取类的信息 首先要获取类的类类型
        // 形参obj 该对象所属类的信息
        Class c = obj.getClass();// 传递的是哪个子类的对象 c就是该        子类的类类型
        // getClass()方法:native修饰代表 存在不是java 代码 ,调度        外用 ///该方法java内调用底层c语言实现

        // 获取累的名称
        System.out.println("类的名称是:"   c.getName());
        // Method类是方法对象
        // 一个成员方法就是一个Method
        // getMethods()方法获取的是所有的public修饰的函数,包括父类        继承而来的
        Method[] ms = c.getMethods();
        // c.getDeclaredMethods()获取的是所有该类自己声明的方法,不        问访问权限.所有。所有。所有
        String[] name = new String[ms.length];
        for (int i = 0; i < ms.length; i  ) {
            // 得到方法的返回值类型--得到的是返回值类型的类类型
            Class returnType = ms[i].getReturnType();
            // 得到返回值名字
            String returnName = returnType.getName();
            // 得到方法的名称
            name[i] = ms[i].getName();
            // 获取参数列表类型--得到的是参数列表的类型的类类型
            Class[] parameterTypes = ms[i].getParameterTypes();
Int params=parameterTypes.length;            
String[] paramNames = new String[params];
            for (int j = 0; j < params; j  ) {
                // 得到参数列表名
                paramNames[j] = ms[j].getName();
            }
        }
    }
}

 

 

通过反射可以获取任何类的类信息

比较牛逼

Class c2=String.class;

获取类的成员变量构造函数信息

成员变量也是对象

是Java.lang.reflect.Field的对象

Field类封装了关于成员变量的操作

 

栗子:通过反射可以获取到任何类的信息

需求:打印类的信息,获取类的成员变量

 

 

package cn.reflect;

import java.lang.reflect.Field;

/**
 * 
 * @author: 房上的猫
 * 
 * @time: 下午3:49:32
 * 
 * @博客地址: https://www.cnblogs.com/lsy131479/
 *
 */

public class myField {
    public static void printFieldMessage(Object obj) {
        Class c = obj.getClass();
        // getFidlds() 方法获取的是类的所有的public的成员变量信息
        Field[] fs = c.getFields();

        // getDeclaredFields() 获取的是该类自己声明的成员信息 不问访问权限.所有。所有。所有
        // Field[] fs = c.getDeclaredFields();

        for (Field field : fs) {
            // 得到成员变量的类型的类类型
            Class fieldType = field.getType();
            // 得到成员变量类型的名字
            String typeName = fieldType.getName();
            // 得到成员变量的名字
            String fieldName = field.getName();
            //

        }

    }
}

 

构造函数也是对象

是Java.lang.Constructor的对象 其中封装了构造函数的信息

栗子:通过反射可以获取到任何类的信息

需求:打印类的信息,获取类的构造函数信息

 

 

package cn.reflect;

import java.lang.reflect.Constructor;

/**
 * 
 * @author: 房上的猫
 * 
 * @time: 下午3:49:32
 * 
 * @博客地址: https://www.cnblogs.com/lsy131479/
 *
 */

public class myCon {
    public static void printConMessage(Object obj) {
        Class c = obj.getClass();
        // getConstructors() 获得所有的共有的构造方法
        Constructor[] cs = c.getConstructors();
        // getDeclaredConstructors() 得到所有的构造方法(必须是自己声明的) 不问访问权限.所有。所有。所有
        // Constructor[] cs = c.getDeclaredConstructors();
        for (Constructor constructor : cs) {
            // 获取构造函数名
            String name = constructor.getName();
            // 获取构造函数的参数列表------>得到的是参数列表的类类型
            Class[] parameterTypes = constructor.getParameterTypes();
            for (Class class1 : parameterTypes) {
                // 获取构造函数参数列表名
                String name2 = class1.getName();
            }
        }
    }
}

 

Class c3=void.class;

本文由必威官网登录发布于游戏编程设计,转载请注明出处:Java 高级开发必修知识---反射