这里有新鲜出炉的 Java 并发编程示例,程序狗速度看过来!
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
下面小编就为大家带来一篇老生常谈 Java 反射机制 (必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
什么是反射机制
反射是 java 语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个 java 的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如 C 或者 C++ 语言中很不就存在这个特性。一个常见的例子是在 JavaBean 中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的 java 中类的属性的。
主要的类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Class 没有公共的构造方法,Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限 (主要提供的是对构造方法使用)
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)
Field 主要提供对类中的成员变量的访问和使用
Class
Class 类也使用了泛型,即是 Class
常用的方法
getConstructor(Class[] params) 获取公共的 (public) 的构造方法,并且限定其中的参数个数和类型可以获得不同的公共构造方法
Constructor[] getConstructors() 返回所有的公共 (public) 的构造方法
getDeclaredConstructor(Class[] params) 获取所有指定的构造方法,但是需要注意的是当获取私有的构造方法的时候需要使用 setAccessible 设置访问权限为 true 才能进行构造,否则出现异常
Constructor[] getDeclaredConstructors() 返所有的构造方法包括 public 和 private,protected 修饰的
T newInstance() 返回的是一个调用默认的构造方法 (public class_name()) 实例化的一个 Object 对象,如果使用泛型那么就返回 T 类型的,反之返回的是 Object 需要强制转换才能使用这个对象调用成员函数和成员变量
Class forName(String class_name) 返回 class 对象,每一个对都有一个方象法返回 Class 对象 (test.class)
Package getPackage() 返回此类所在的包名 (package demo) 当然也可以使用 Package.getName() 获得包的名字 (demo) 比如 constructor.getPackage().getName()
int getModifiers() 返回的是类的修饰符的整数 类型 (修饰符的类型有 public private protected) 其中得到整数可以使用 Modifier 中 toString(int num)得到 public,private,protected 的类型, 比如 Modifier.toString(class1.getModifiers())
*Method getMethod(String name, Class<?>... parameterTypes) 返回指定参数的方法 Method 对象, 注意这里仅仅是返回的时公共的方法 (public) 比如: Method method=class1.getMethod("display",new Class[]{int.class}) 这里的 display 是方法的名字,有一个参数,类型为 int
Method[] getMethods() 获取所有的公共的方法 (public) 返回的是一个数组(Method)
Method getDeclaredMethod(String name,Class<?>... parameterTypes) 返回所有的指定的参数的方法 (public,private,protected,但是不包括继承的), 其中参数可以为 null(无参数)
Method[] getDeclaredMethods() 获取所有的方法
Field getField(String name) 指定名字的公共成员变量 (public)
Field[] getFields() 获取所有的公共的成员变量
Field getDeclaredField(String name) 获取所有的指定名称的成员变量 (public,protected,private), 同样在调用私有成员变量的时候需要先设置访问的权限, field.setAccessible(true)
Field[] getDeclaredFields() 获取所有的成员变量 (public,protected,private)
getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
URL getResource(String name) 查找指定名称的资源 (图片,文件...) 注意这个资源一定要和指定类在一个包中,否则返回 null,比如查找 Test 类下的 airplane.png 图片: Test.class.getResource("airplane.png")这里返回的将是绝对路径
获取 Class 的对象并且实例化
使用 Class.forName(String className) 其中 className 一定是包含包的名字,下面的 demo 就是包的名字,Test 是类的名字。这是最常用的方法,学过 JDBC 的都知道加载驱动的时候就是使用的 Class.forName()
- /*
- * 第一种使用forName(String className),其中className一定是包含包的名字,下面的demo就是包的名字,Test是类的名字
- */
- Class cls=Class.forName("demo.Test");
- Test test=(Test)cls.newInstance(); //这里只是使用了默认的构造方法实例化对象
使用类名. class
- Class cls = Test.class;
使用对象. getClass()
- Test test = new Test();
- Class cls = test.getClass();
Constructor
主要是用来对类的构造方法进行操作的,可以看出这个也使用了泛型,和上面的 Class 是一样的,注意这里如果没有使用泛型,那么原本放回 T 类型的现在都是返回 Object
常用的方法
T newInstance(Object parms) 使用带有参数的构造方法实例化对象,如果使用了泛型,那么返回的就是 T 类型的,反之返回的是 Object 类型的,需要强制转换
getName() 以字符串的形式返回构造方法的名称,具体的路径包含包名 (demo.Test)
int getModifiers() 和 Class 类中的方法一样
Method
主要提供的是对类中的方法的操作
常用的方法
Object invoke(Object obj,object args) 使用得到的 Method 对象调用方法,obj 是类的已经构造好的对象,如果是静态方法直接写 null, 因为静态方法的调用不需要对象,返回值是 Object 类型的,如果接受返回值,需要使用强制转换成相应的类型, args 是传入的参数, 如果有多个参数,那么可以直接在后面用逗号添加或者直接创建数组 new Object[]{22,"chenjiabing"} 比如:method.invoke(test,22,"chenjiabing") method.invoke(test,new Object[]{22,"chenjiabing"}) 注意:如果调用的 private 类型的方法,那么需要在前面设置访问的权限, method.setAccessible(true)
String getName() 返回此方法的名字 (display)
Modifier getModifiers() 返回此方法的修饰符的类型表示的整数 (public,private...), 可以使用 Modifier.toString() 转换成字符串形式
Class getReturnType() 返回这个方法的返回类型
String toString() 返回这个方法表示的字符串的形式
Field
主要提供对类的成员变量的操作
常用方法
String getName() 返回变量名字
Object get(Object obj) 返回此变量在指定对象中的值,因为在构造对象的时候每一个传入的变量的值都不一样,因此需要使用对象 obj。obj 表示传入的对象,返回的 Object 类型,因此需要强制转换
void set(Object obj,Object value) 改变 obj 对象上的变量的值为 value
Modifier getModifiers() 返回整数表示修饰的类型
String getType() 获取变量的类型 (int,String,double float.....)
Modifier
Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。
常用的方法
static String toString(int mode) 将代表修饰符的整数形式转换为字符串形式的修饰符,比如将 1 转换成 public
static isInterface(int mode) 如果整数参数包括 interface 修饰符,则返回 true,否则返回 false
static isStatic(int mode)
static isPrivate(int mode)
static isPublic(int mode)
static isAbstract(int mode)
实例
- Modifier.toString(Test.class.getModifiers()) //得到Test类的修饰符
使用
有了上面的铺垫,我们就可以使用上面的这些类进行操作了,在进行操作之前,我们需要先定义一个类 Test, 放在 demo 包下,内容如下
- package demo;
- import java.util.jar.Attributes.Name;
- import javax.print.attribute.standard.MediaSize.NA;
- public class Test {
- public String name;
- private int age;
- public Test() {
- this.name = "陈加兵";
- this.age = 23;
- }
- public Test(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public void display() {
- System.out.println("name=" + this.name + "----age=" + this.age);
- }
- public void set(String name, int age) {
- this.name = name;
- this.age = age;
- }
- private int getAge() {
- return this.age;
- }
- }
实例化对象
使用 Class 默认的构造 newInstance()
- Class class1=Class.forName("demo.Test"); //静态加载Class
- Test test=(Test)class1.newInstance(); //调用默认的构造方法(public Test())实例化对象,由于没有使用泛型,因此需要强转
- test.display(); //调用display方法
使用 Class 中的 getConstructor() 方法构造对象, 需要注意的使用 private 类型构造方法时一定要先设置访问权限为 true-constructor.setAccessible(true);
- /*
- *调用public Test(String name,int age)得到Constructor的两种形式
- * 1.Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
- * 2.Constructor constructor=class1.getConstructor(String.class,int.class);这个和上面的是一样的,就是使用的参数形式不一样
- *
- *
- *
- *
- *使用newInstance()构造对象的两种方式
- * 1.Test test=(Test)constructor.newInstance(new Object[]{"chenjiabing",22});
- * 2.Test test=(Test)constructor.newInstance("chenjiabing",22); 只是形式不同而已,不过我还是喜欢上面的形式
- *
- */
- /*
- * 调用public Test(String name,int age)
- * Class.getConstructor()得到的是公共的构造方法,如果有私有的构造方法,那么就会报错,这时就要使用getDeclaredConstructor(Class<?>... parameterTypes)
- * Test test=(Test)constructor.newInstance("陈加兵",22);
- *
- *
- * 调用public Test()
- * Constructor constructor=class1.getConstructor(null);
- * Test test=(Test)constructor.newInstance(null);
- *
- *
- * 调用private Test(int age)
- * Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class});
- constructor.setAccessible(true); //因为private类型是不可以直接访问的,因此需要设置访问权限为true
- Test test=(Test)constructor.newInstance(new Object[]{1000});
- */
- Class class1 = Class.forName("demo.Test");
- //访问public Test(String name,int age)
- // Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class});
- // Test test=(Test)constructor.newInstance("陈加兵",22);
- //访问默认的构造方法
- // Constructor constructor=class1.getConstructor(null);
- // Test test=(Test)constructor.newInstance(null);
- //访问private类型的构造方法
- Constructor constructor = class1.getDeclaredConstructor(new Class[] {
- int.class
- });
- constructor.setAccessible(true);
- Test test = (Test) constructor.newInstance(new Object[] {
- 1000
- });
- test.display();
成员方法的操作
使用 Class.getMethod() 和 Class.getDeclaredMethod() 方法获取方法,这两个方法的区别前面已经说过了,注意的是调用私有成员方法的之前一定要设置访问权限 (method.setAccessible(true))
Method 类中的其他方法前面也已经说过了,详细使用请自己尝试
- /*
- * 获取Method对象的两种方式:
- * 1.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
- * 2.Method method_set=class1.getMethod("set", String.class,int.class);
- *
- *
- * 使用Method.invoke()调用方法的两种方式
- * 1.Object o=method_set.invoke(test, new Object[]{"陈加兵",200});
- * 2.Object object=method_set.invoke(test, "陈加兵",2000);
- */
- /*
- * 获取公共方法(public):
- * 1.Method method=class1.getMethod("display",null); //public void display()
- * 2.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); //获取public void set(String name,int age)
- *
- *
- * 获取私有方法(private,protected)
- * 1.Method method_getAge=class1.getDeclaredMethod("getAge", null);
- */
- //使用构造方法构造一个Test对象
- Class class1 = Class.forName("demo.Test");
- Constructor < Test > constructor = class1.getDeclaredConstructor(new Class[] {
- String.class,
- int.class
- });
- Test test = constructor.newInstance(new Object[] {
- "陈加兵",
- 22
- });
- Method method = class1.getMethod("display", null); //获取public void display()方法的Method对象
- Object obj = method.invoke(test, null); //调用方法display
- //获取public void set(String name,int age)
- // Method method_set=class1.getMethod("set", new Class[]{String.class,int.class});
- Method method_set = class1.getMethod("set", String.class, int.class);
- // Object o=method_set.invoke(test, new Object[]{"陈加兵",200});
- Object object = method_set.invoke(test, "陈加兵", 2000);
- test.display();
- //获取私有方法private int getAge()
- Method method_getAge = class1.getDeclaredMethod("getAge", null);
- method_getAge.setAccessible(true); //必须设置访问权限为true
- //判断返回值类型是否为int类型的
- if ("int".equals(method_getAge.getReturnType().toString())) {
- int ReturnData = (int) method_getAge.invoke(test, null); //调用并且获取返回值
- System.out.println(ReturnData);
- }
成员变量的操作
主要使用的 Field 类,前面已经详细的说过了
- /*
- * 获取public修饰的成员变量:
- * 1.Field field=class1.getField("name"); //获取public的成员变量name的Filed对象
- *
- * 获取private,protected修饰的成员变量:
- * 1. Field field2=class1.getDeclaredField("age");
- */
- Class class1=Class.forName("demo.Test");
- Test test=new Test("陈加兵",1000);
- Field field=class1.getField("name"); //获取public的成员变量name的Filed对象
- System.out.println(field.get(test)); //获得test对象中的name属性的值
- //获取private int age的Field对象
- Field field2=class1.getDeclaredField("age");
- field2.setAccessible(true); //设置访问权限
- System.out.println(field2.get(test));
以上这篇老生常谈 Java 反射机制 (必看篇) 就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持 PHPERZ。
来源: http://www.phperz.com/article/17/0817/338258.html