10
回答
java反射机制 问题

如果有两个类A和B

B继承于A,

A:有字段name    以及getName和setName

B:有AGE   以及get和set方法

怎么使用反射机制获取所有的方法。。并且设置age或者name的值。。。然后调用get方法???

举报
owenG
发帖于3年前 10回/508阅
共有10个答案 最后回答: 3年前

1.Class c= Class.forName("B");

 B b = (B)c.newInstance();

2.通过c.getMethod(name,parameterTypes)获得方法,返回的是Method对象(method

3.调用:method.invoke(b,参数列表)

好像是这样的


public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

引用来自“英强”的评论

public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

我想问的其实是使用getDeclaredMethods来获取所有的方法。。然后使用METHOD来设置和打印内容、、、

引用来自“英强”的评论

public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

引用来自“owenG”的评论

我想问的其实是使用getDeclaredMethods来获取所有的方法。。然后使用METHOD来设置和打印内容、、、
如果不知道自己初始化的是什么类,那就必须用你说的方法。判断是否为set方法,是的话,获取参数类型,注入参数执行方法。然后再获取get方法执行就可以了。
--- 共有 3 条评论 ---
owenG回复 @英强 : 假设不知道有那个方法。。然后反射出set方法。。。然后调用get 3年前 回复
英强回复 @owenG : 举例子前要有前提,先把前提说明了才行。像你的问题里,如果都知道B这个类了,其实就没必要用反射。 3年前 回复
owenG@英强 能举个例子吗??? 3年前 回复

引用来自“英强”的评论

public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

而且你这样的话会报错的、、、Exception in thread "main" java.lang.ClassNotFoundException: B
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.aspectgaming.facebook.logserver.C.main(C.java:47)

引用来自“英强”的评论

public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

而且你这样的话会报错的、、、Exception in thread "main" java.lang.ClassNotFoundException: B
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.aspectgaming.facebook.logserver.C.main(C.java:47)

引用来自“owenG”的评论

我这两个类都是没包的。你肯定放到自己的某个包里面了。那样的话,要改下Class.forName的参数,加上你的包名

引用来自“英强”的评论

public class A {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

public class B extends A {

	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
		B b = (B)Class.forName("B").newInstance();
		b.setAge(1);
		b.setName("Cevin");
		
		System.out.println(b.getAge());
		System.out.println(b.getName());
	}
}

看main函数,这能满足你的需求吗?

而且你这样的话会报错的、、、Exception in thread "main" java.lang.ClassNotFoundException: B
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.aspectgaming.facebook.logserver.C.main(C.java:47)

引用来自“owenG”的评论

我这两个类都是没包的。你肯定放到自己的某个包里面了。那样的话,要改下Class.forName的参数,加上你的包名

引用来自“英强”的评论

 public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
       B b = B.class.newInstance();
       b.setAge(1);
       b.setName("Cevin");
        
       System.out.println(b.getAge());
       System.out.println(b.getName());

   }

我改成这样也不行啊

你要的是这样的效果?

public class Main {
	public static void main(String[] args) {
		B b = new B();
		DynamicBean d = new DynamicBean(b);
		d.set("name", "abc");
		d.set("age", 1);
		System.out.println(d.get("name"));
		System.out.println(d.get("age"));
	}
	
	public static class A {
		private String name;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

	}

	public static class B extends A {
		private int age;

		public int getAge() {
			return age;
		}

		public void setAge(int age) {
			this.age = age;
		}

	}
}



import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class DynamicBean {
	private final Object object;
	private final Map<String, Method> getters = new HashMap<String, Method>();
	private final Map<String, Method> setters = new HashMap<String, Method>();

	public DynamicBean(Object object) {
		this.object = object;
		this.init();
	}

	private void init() {
		for (Method method : object.getClass().getMethods()) {
			String methodName = method.getName();
			if (method.getParameterTypes().length == 0) {
				if (methodName.startsWith("get")) {
					String name = extractName(methodName, "get");
					if (name != null) {
						getters.put(name, method);
					}
				} else if (methodName.startsWith("is")) {
					Class<?> type = method.getReturnType();
					if (type == boolean.class || type == Boolean.class) {
						String name = extractName(methodName, "is");
						if (name != null) {
							getters.put(name, method);
						}
					}
				}
			} else if (method.getParameterTypes().length == 1) {
				if (methodName.startsWith("set")) {
					String name = extractName(methodName, "set");
					if (name != null) {
						setters.put(name, method);
					}
				}
			}
		}
	}

	private String extractName(String methodName, String prefix) {
		String name = methodName.substring(prefix.length());
		if (name.length() == 0
				|| Character.isUpperCase(name.charAt(0)) == false) {
			return null;
		}
		return Character.toLowerCase(name.charAt(0)) + name.substring(1);
	}

	public Object get(String name) {
		try {
			return getters.get(name).invoke(object);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public void set(String name, Object value) {
		try {
			setters.get(name).invoke(object, value);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}




--- 共有 2 条评论 ---
canghailan回复 @owenG : 有点长,在下面回复了。 3年前 回复
owenG原理能讲讲吗??? 3年前 回复

Java的get方法分两种,boolean类型命名规则是isXxx(字段名首字母大写),其他类型的是getXxx,get方法的参数长度为0。

遍历所有public方法(class.getMethods),根据这两个命名规则就可以把所有get方法找到,当然特殊情况先不考虑。

Java的set方法只有一种,命名规则是setXxx,set方法的参数长度为1,返回值为void。和get方法一样可以把所有set方法找到。

把它们以字段名为键,get、set方法为值放入Map中,这样就可以通过字段名找到对应的方法了,用Method.invoke调用方法即可获取、设置对应的字段值。

顶部