简介:
总结于imooc课程: http://www.imooc.com/learn/199
本文通过几个简单的例子,介绍Class类的使用,方法和成员变量的反射,以及通过反射了解集合泛型的本质等知识。
1.Class类的使用
/**
* 使用java.lang.Class类动态加载一个类,编译时不对类是否存在以及对错进行检查,运行时检查
*/
public class OfficeBetter {
public static void main(String[] args) {
args = new String[1];
Scanner input = new Scanner(System.in);
args[0] = input.next();
try {
Class> c = Class.forName("动态加载."+args[0]);
IOfficeStart officeStart = (IOfficeStart)c.newInstance();
officeStart.start();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
} finally{
input.close();
}
}
}
//office功能接口
public interface IOfficeStart {
void start();
}
//实现1
public class Word implements IOfficeStart{
@Override
public void start() {
System.out.println("Word...start...");
}
}
//实现2
public class Excel implements IOfficeStart{
@Override
public void start() {
System.out.println("Excel...start...");
}
}
2.通过对象或类名获取类的信息
/**
* 通过类对象来获取该类的所有方法、构造函数、变量
*/
public class ClassUtil {
public static void main(String[] args) {
Class c1 = int.class;
Class c2 = void.class;
System.out.println(c1.getName());
System.out.println(c2.getName());
ClassUtil.printClassMethods(new Double(1.0d));
ClassUtil.printClassFields(new Integer(1));
ClassUtil.printClassConstructors(new String());
}
/**
* 打印obj对象所在类的所有方法
* @param obj
*/
public static void printClassMethods(Object obj){
//首先获取类的类类型
Class c = obj.getClass();
System.out.println(c.getName() + "类所有的方法:");
//getMethods返回所有public方法,包括继承的方法
//getDeclaredMethods()返回所有的方法,不包括继承的方法
Method []ms = c.getMethods();
//遍历集合打印每个方法,包括方法返回值,方法名,方法参数
for (int i = 0; i < ms.length; i++) {
Method m = ms[i];
//返回类型
System.out.print(m.getReturnType().getSimpleName() + " ");
//方法名
System.out.print(m.getName() + " (");
//参数集合
Class []args = m.getParameterTypes();
for (Class class1 : args) {
System.out.print(class1.getSimpleName() +",");
}
System.out.println(")");
}
System.out.println("\n\n");
}
/**
* 打印obj对象所在类的所有构造函数
*/
public static void printClassConstructors(Object obj){
Class c = obj.getClass();
System.out.println(c.getName() + "类的所有构造函数:");
Constructor []cs = c.getDeclaredConstructors();
for (int i = 0; i < cs.length; i++) {
System.out.print(cs[i].getName() + " (");
Class []paras = cs[i].getParameterTypes();
for (Class class1 : paras) {
System.out.print(class1.getName() + ",");
}
System.out.println(")");
}
System.out.println("\n\n");
}
/**
* 打印obj对象所在类的所有变量
*/
public static void printClassFields(Object obj){
Class c = obj.getClass();
System.out.println(c.getName() + "类的所有成员变量:");
Field[] fields = c.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
System.out.println(field.getType().getName() + " " + field.getName());
}
System.out.println("\n\n");
}
}
3.通过对象获取到所在类的某个方法后,通过反射的方式调用该方法
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args){
A a = new A();
//下面通过对象a来反射调用方法
Class extends A> c = a.getClass();
try {
//Method m1 = c.getMethod("print1", new Class[]{String.class,String.class});
Method m1 = c.getMethod("print1", String.class,String.class);
//Method m2 = c.getMethod("print2",new Class[]{});
Method m2 = c.getDeclaredMethod("print2");
m1.invoke(a,"HELLO","world");
m2.invoke(a);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class A{
public void print1(String a,String b){
System.out.println(a.toLowerCase() +" "+ b.toUpperCase());
}
public void print2(){
System.out.println("hello world");
}
}
4.通过反射理解泛型(不能算是应用场景)
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
list2.add("hello");//ok
//list2.add(1111);//false
System.out.println(list1.getClass() == list2.getClass());//输出true
//因为带泛型和不带泛型通过反射得到类类型都发现是==的
//所以推测泛型的实质是在编译之前起到提醒的作用,在编译之后是没有泛型的
//通过反射验证
try {
Method m = list1.getClass().getMethod("add", Object.class);
m.invoke(list2, 1111);
System.out.println(list2);//测试是否add进去1111
//for (String string : list2) {
//System.out.print(string);
//}此时不能这么遍历
for (Object obj : list2) {
System.out.print(obj + " ");
}//发现可以add
} catch (Exception e) {
// TODO: handle exception
}
}
}