Java程序中的各个类属于同一事物,描述这类事物的java类名就是Class,想要学习反射就必须先理解Class。
每一个类的实例对象在内存中都有相对应的字节码。
一个类被类加载器加载到内存中,占用储存空间,而在该储存空间中的就是该类的字节码,不同类的字节码是不同的,所以在内存中也是不相同的。
在内存中占用的空间可以用对象来表示,这些对象的类型就是Class。
概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射就是把java类中的各种成分映射成相对应的java类
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
想要对一个类进行反射,必须获取该类的字节码文件,因为反射是在运行时才调用类的方法和对象,所以避过编译期的一些异常,如:可用反射在Integer泛型的集合中,添加String类型的元素,而不报异常。
获取字节码文件的三种方式
1.Class clazz = 对象.getClass();
通过对象获取字节码文件对象
2.Class clazz = 类名.class;
每一个数据类型都具备静态的class属性
3.Class clazz = Class.forName(“类名”);
Class类的forName();静态方法,只需要传入一个字符串类名,这种方法最为常用。
示例:
package itheima;
public class Person {
private String name;
private int age;
public Person()
{
System.out.println("hello reflect");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
System.out.println(name+":::::"+age);
}
}
package itheima;
public class GetClass {
public static void main(String[] args)throws ClassNotFoundException {
//第一种方式
Person p = new Person();
Class c1 = p.getClass();
System.out.println(c1);
System.out.println("------------------------------");
//第二种方式
Class c2 = Person.class;
System.out.println(c1);
System.out.println("------------------------------");
//第三种方式
Class c3 = Class.forName("itheima.Person");
System.out.println(c1);
}
}
通过反射获取构造方法:
获取构造方法有两种情况,一是无参构造方法,二是有参构造方法。
示例:
package itheima;
public class Person {
private String name;
private int age;
public Person()
{
System.out.println("hello reflect");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
System.out.println(name+":::::"+age);
}
}
package itheima;
import java.lang.reflect.Constructor;
public class GetConstructor {
public static void main(String[] args) throws Exception{
String name = "itheima.Person";//得到该类的名字
//把类加载进内存,产生Class对象
Class clazz = Class.forName(name);
createConstructor1(clazz);
createConstructor2(clazz);
}
//方法一,通过Object类中的newInstance方法,获取Person类的无参构造函数
public static void createConstructor1(Class clazz)throws Exception
{
Object obj = clazz.newInstance();//调用类的无参构造方法
}
//方法二,通过的到构造方法对象,在进行初始化
public static void createConstructor2(Class clazz)throws Exception
{
//获取指定的构造方法对象
Constructor constructor = clazz.getConstructor(String.class,int.class);
//通过构造器对象的newInstance方法对对象进行初始化
Object obj = constructor.newInstance("剑圣",20);
}
}
获取Class字段:
示例:
package itheima;
public class Person {
private String name;
private int age;
public Person()
{
System.out.println("hello reflect");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
System.out.println(name+":::::"+age);
}
}
package itheima;
import java.lang.reflect.Field;
public class GetField {
public static void main(String[] args) throws Exception{
//得到该类的名字
String name = "itheima.Person";
//把类加载进内存,产生Class对象
Class clazz = Class.forName(name);
//得到字段对象,getDeclaredField()既可以获取公共方法,又可以获取私有方法
Field field = clazz.getDeclaredField("name");
//暴力访问,取消私有的访问权限
field.setAccessible(true);
//得到构造方法
Object obj1 = clazz.newInstance();
//为指定的字段赋值
field.set(obj1, "赵信");
//获取指定的字段
Object obj2 = field.get(obj1);
//打印指定的字段
System.out.println(obj2);
}
}
获取Class的方法
示例:
package itheima;
public class Person {
private String name;
private int age;
public Person()
{
System.out.println("hello reflect");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name,int age)
{
this.name=name;
this.age=age;
System.out.println(name+":::::"+age);
}
public static void staticMethod1(String str)
{
System.out.println("有参数的静态方法:"+str);
}
public static void staticMethod2()
{
System.out.println("无参数的静态方法:");
}
private void privateMethod()
{
System.out.println("私有方法");
}
public void paramentMethod(String str)
{
System.out.println("有参数方法");
}
public void paramentMethod()
{
System.out.println("无参数方法");
}
}
package itheima;
import java.lang.reflect.Method;
public class GetMethod {
public static void main(String[] args)throws Exception {
//得到该类的名字
String name = "itheima.Person";
//把类加载进内存,产生Class对象
Class clazz = Class.forName(name);
//得到该类的所有方法,存入集合中
Method[] methods = clazz.getDeclaredMethods();
//遍历出该类的所有方法
for(Method method : methods)
{
System.out.println(method);
}
m1(clazz);
m2(clazz);
m3(clazz);
m4(clazz);
m5(clazz);
}
//获取有参数的静态方法
public static void m1(Class clazz)throws Exception
{
//得到该类的指定方法对象
Method method = clazz.getDeclaredMethod("staticMethod1", String.class);
//调用该类的指定方法
method.invoke(null, "瑞雯");
}
//获取无参数的静态方法
public static void m2(Class clazz)throws Exception
{
//得到该类的指定方法对象
Method method =clazz.getDeclaredMethod("staticMethod2", null);
//调用该类的指定方法
method.invoke(null, null);
}
//获取私有方法
public static void m3(Class clazz)throws Exception
{
//得到该类的指定方法对象
Method method = clazz.getDeclaredMethod("privateMethod", null);
//暴力访问,取消私有的访问权限
method.setAccessible(true);
//得到该类的对象
Object obj = clazz.newInstance();
//调用该类的指定方法
method.invoke(obj, null);
}
//获取无参数一般方法
public static void m4(Class clazz)throws Exception
{
//得到该类的指定方法对象
Method method = clazz.getDeclaredMethod("paramentMethod", null);
//得到该类的对象
Object obj = clazz.newInstance();
//调用该类的指定方法
method.invoke(obj, null);
}
//获取有参数一般方法
public static void m5(Class clazz)throws Exception
{
//得到该类的指定方法对象
Method method = clazz.getDeclaredMethod("paramentMethod", String.class);
//得到该类的对象
Object obj = clazz.newInstance();
//调用该类的指定方法
method.invoke(obj, "蛮三刀");
}
}
题目:
把points类中的所有字符串对象中的a换成b;
代码:
import java.lang.reflect.*;
class FiledsTest
{
public static void main(String[] args) throws Exception
{
Points p1 = new Points(1,3);
filedsDemo(p1);
System.out.println(p1);
}
public static void filedsDemo(Object obj)throws Exception
{
Field[] fields = obj.getClass().getDeclaredFields();//得到所有字段,包括私有字段
for(Field field : fields)//遍历该类的所有字段
{
if(fields.getType() == String.class)//判断是否为字符串类型
{
field.setAccessible(true);//暴力访问
String oldValue = (String)field.get(obj);//得到指定字段的值
String newValue = oldValue.replace('a','b');//字符串的替换
field.set(obj,newValue);//设置指定的字段的值
}
}
}
}
class Points
{
private int x;
public int y;
private String str = "aaa";
public String str1 = "aca";
private String str2 = "abc";
public Points(int x,int y)
{
this.x=x;
this.y=y;
}
public String toString()
{
return str+":::::"+str1+":::::"+str2;
}
}