Class类的使用
package com.froe.reflect;
public class ClassDemo1 {
public static void main(String[] args) {
// foo的实例表示
Foo foo1 = new Foo();
// Class是私有化的构造函数 只有java的虚拟机才能访问
// Foo这个类 也是一个实例对象 Class类的实例对象 如何表示呢 三种方法
// 任何一个类都是Class的实例对象 三种
// 任何一个类都有一个隐藏的静态成员变量 Class
Class c1 = Foo.class;
// 第二种 已经知道该类的对象通过getClass方法
Class c2 = foo1.getClass();
/**
* 官网称 c1 c2表示了Foo类的类类型(Class Type)
*
* 万事万物皆对象 类也是对象 是Class类的实例对象 我们把这个对象称做 该类类类型
*/
// 不管c1 还是 c2 都代表foo类的类类型 一个类只可能是Class类的一个实例对象
System.out.println(c1 == c2);
// 第三种
Class c3 = null;
try {
c3 = Class.forName("com.froe.reflect.Foo");
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} // 全类名
System.out.println(c2 == c3);
System.out.println(c3 == c1);
//我们完全可以通过类的类类型 创建该类的对象实例--->通过c1 or c2 or c3创建Foo的实例
try {
Foo foo=(Foo)c1.newInstance();//c1是哪个类的类对象创建出的就是哪个类的对象实例,所以此处我们需要进行强制转换
foo.print();//需要有无参数的构造方法
} catch (InstantiationException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
class Foo {
void print() {
System.out.println("Foo");
}
} // Foo类的对象是foo1 Foo类的类类型是Class
java动态加载类
Class.forName("类的全称")
1.这个不仅表示了累的类类型 还代表了动态加载类
2.编译时刻加载类是静态加载类 运行时刻加载类是动态加载类
相信很多人都遇到过一些问题就是假如我们有类中有100个方法 其中有一个报错此类是不是就运行不了了呢!
这个时候我们就使用我们的动态加载来解决该问题了
package com.froe.reflect;
public class OfficeBetter {
public static void main(String[] args) throws Exception {
//这个就是动态加载类
Class c = Class.forName(args[0]);//返回的是这个类的类类型
//通过类类型创建对象
OfficeAble oa =(OfficeAble)c.newInstance();//OfficeAble是个接口 此处想使用哪个方法就让哪个方法实现此接口
oa.start();
}
}
获取类的信息
首先是我们要自己写的工具类,(想获取一个类的信息,首先肯定是要获取其类类型)
package com.froe.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ClassUtil {
/**
* 打印类的信息 包括成员函数 成员变量(只获取成员函数)
* @param obj该对象那个所属的类信息
*/
public static void printClassMethodMessage(Object obj) {
//要获取类的信息 首先获取类的类类型
Class c=obj.getClass();//传递的哪个子类的对象 c就是该子类的类型
//获取类的名称
System.out.println("类的名称是"+c.getName());
/*java里面方法是method对象
*Method类 方法对象
*一个成员方法就是一个 Method对象 里面封装了操作子类的方法
*getMethods()方法获取的事所有的public的函数 包括父类继承而来的
*getDeclareMethods()获取的是所有类自己声明的方法 不问访问权限
*/
Method[] ms=c.getMethods();//getDeclareMethods()
// Method[] ms = c.getDeclaredMethods();
for(int i=0;i<ms.length;i++) {
//得到方法的返回值类型的类类型
Class returnType=ms[i].getReturnType();
System.out.print(returnType.getName()+" ");
//得到方法的名称
System.out.print(ms[i].getName()+"(");
//获取参数类型---->得到的是参数列表的类型的类类型
Class[] paramTypes=ms[i].getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName());
}
System.out.println(")");
PringFileldMessage(c);
}
}
/*
* 这个只获取了成员变量的信息
*/
public static void PringFileldMessage(Object obj) {
Class c=obj.getClass();
/**
* 成员变量也是对象
* java.lang.reflect.Field
* Field类封装了关于成员变量的操作
* getFields()方法获取的是所有的public的成员变量的信息
* getDeclaredFields()获取的是该类自己声明的成员变量的信息
*
*/
//Field[] fs=c.getFields();
Field[] fs=c.getDeclaredFields();
for (Field field : fs) {
//得到成员变量的类型的类类型
Class firldType=field.getType();
String typeName=firldType.getName();
//得到成员变量的名字
String frildName=field.getName();
System.out.println(typeName+" "+frildName);
}
}
/*
* 打印对象的构造函数的信息
*/
public static void printConMessag(Object obj) {
Class c=obj.getClass();
/*
* 构造函数也是对象
* java.lang.Constructor中封装了构造函数的信息
* getConstructors();获得所有的public的构造函数
* getDeclaredConstructors得到所有的构造函数
*/
//Constructor[] cs=c.getConstructors();
Constructor[] cd=c.getDeclaredConstructors();
for (Constructor constructor : cd) {
System.out.print(constructor.getName()+"(");
//获取构造函数的参数列表---->得到的是参数列表的类类型
Class[] paramTypes=constructor.getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName());
}
System.out.println(")");
}
}
}
然后我们来调用啦
package com.froe.reflect;
public class ClassDemo3 {
public static void main(String[] args) {
//打印出String的信息
String s="hello";
ClassUtil.printClassMethodMessage(s);
System.out.println("--------------------------------------------------");
//打印出Integer的信息
Integer i=1;
ClassUtil.printClassMethodMessage(i);
System.out.println("--------------------------------------------------");
ClassUtil.PringFileldMessage("hello");
System.out.println("===============");
ClassUtil.printClassMethodMessage(new Integer(1));
System.out.println("--------------------------------------------------");
ClassUtil.printConMessag("hello");
ClassUtil.printConMessag(new Integer(1));
}}
java反射的基本操作
1.如何获取某一个方法
方法的名称和方法的参数列表才是唯一能决定某个方法
2方法的反射操作
method.invoke(对象,参数列表)
package com.froe.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MethodDemo1 {
public static void main(String[] args) {
//获取print(int int)方法 1.要获取一个方法 首先要获取类的信息 首先获取类的类类型
A a1=new A();
Class c=a1.getClass();
/*获取方法 名称和参数列表来决定
*getMethod获取的public的方法
*getDeclaredMethod获取的自己声明的方法
*/
try {
//Method m=c.getMethod("print", new Class[] {int.class,int.class});
Method m=c.getMethod("print", int.class,int.class);
//方法的反射操作
//常规写法 a1.print(1, 22); 方法的反射 是使用m对象来进行方法调用 效果是一样的
//方法如果没有返回值返回null 有返回值返回具体的返回值
// Object obj= m.invoke(a1,new Object[] {1,24});
Object obj=m.invoke(a1, 10,20);
System.out.println("====================");
//获取print(String String)
Method m1=c.getMethod("print", String.class,String.class);
//对方法进行反射操作
obj=m1.invoke(a1,"hello","WORLD");
System.out.println("=================");
Method m2=c.getMethod("print");
//m2.invoke(a1, new Object[] {});
m2.invoke(a1);
} catch (NoSuchMethodException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (SecurityException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
class A{
public void print() {System.out.println("hellowrod");}
public void print(int a,int b)
{System.out.println(a+b);}
public void print(String a,String b)
{System.out.println(a.toUpperCase()+b.toLowerCase());}
}
java通过反射了解集合泛型的本质
package com.froe.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class MethodDemo2 {
public static void main(String[] args) {
ArrayList list=new ArrayList();
ArrayList<String> list1=new ArrayList<String>();
list1.add("hello");
//list1.addAll(1);
Class c1=list.getClass();
Class c2=list1.getClass();
System.out.println(c1==c2);
//反射的操作 都是编译之后的操作
//c1==c2结果返回true说明编译之后集合的泛型是去泛型化的
//java集合的泛型是为了防止错误输入的 只在编译阶段有效 绕过编译就无效了
//验证:我们可以通过方法的反射绕过编译
Method m;
try {
m = c1.getMethod("add", Object.class);
m.invoke(list1, 1);
System.out.println(list1.size());//绕过编译去操作 就绕过了泛型
System.out.println(list1);
/*for (String string : list1) { 此时不可以用foreach遍历
System.out.println(string);
}*/
} catch (NoSuchMethodException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (SecurityException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}}