目录
创建一个Person类
public class Person {
private String name;
int age;
public Person(){
name="小心";
age=10;
};
public Person(String name , int age) {
this.name = name;
this.age = age;
}
private Person(String name ) {
this.name = name;
}
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 String toString(){
return name+"..."+age;
}
public int hashCode(){
return this.name.hashCode()+this.age;
}
public boolean equals(Object o){
/* if(o==null){
return false;
}*/
if(this==o)
return true;
if(o instanceof Person){
Person other=(Person) o;
return this.name.equals(other.name) && this.age==other.age;
}
return false;
}
private void show(){
System.out.println("我是私有方法");
}
}
直接调用Person类
反射之前,可以创造类的对象,通过对象调用其内部属性、方法,但是不可以调用其内部私有结构:比如私有属性、私有方法和私有构造器。
static void test(){
Person p=new Person();
System.out.println(p.toString());
}
获取Class类的四种方式
static void reflect() throws ClassNotFoundException {
System.out.println("------获取反射的四种方式------");
//方式一:
Class cls1=Person.class;
//方式二:使用较少,通常利用反射去构造类实例,此方式却是利用类实例得到反射
Person p=new Person();
Class cls2=p.getClass();
//方式三:推荐使用此方式
Class cls3=Class.forName("Test.Person");//类的路径名
//Class cls3=Class.forName("java.lang.String");
//方式四:使用类加载器
ClassLoader loader=Reflectiontest.class.getClassLoader();
Class cls4=loader.loadClass("Test.Person");
System.out.println(cls1==cls2);//true
System.out.println(cls2==cls3);//true
System.out.println(cls3==cls4);//true
//对于数组,只要元素类型跟数组维度一致,则获取的Class类相同
}
通过反射访问公共构造函数、属性、方法
//通过反射实现上述对公共构造函数、属性、方法的操作
static void test1() throws Exception {
Class cls=Person.class;
//调用构造函数
Constructor cons=cls.getConstructor(String.class, int.class);
Object obj=cons.newInstance("阿反",1);
Person newP=(Person) obj;
//调用默认构造函数
// Object obj1=cls.newInstance();
//Person newP=(Person) obj1;
System.out.println(newP.toString());
//调用指定方法
Method hashcode= cls.getDeclaredMethod("hashCode");
System.out.println(hashcode.invoke(newP));
Method ageset= cls.getDeclaredMethod("setAge", int.class);
ageset.invoke(newP,3);
System.out.println(newP.toString());
//调用指定属性
Field age=cls.getDeclaredField("age");
age.set(newP,18);
System.out.println(newP.toString());
}
通过反射调用类的私有属性和方法
static void test2() throws Exception {
System.out.println("----------通过反射调用私有属性和方法---------");
Class cls=Person.class;
// Constructor [] con=cls.getDeclaredConstructors();
// for ( Constructor c:con){
// System.out.println(c.getName());
// }
//调用私有构造函数
Constructor cons=cls.getDeclaredConstructor(String.class);
cons.setAccessible(true);//设置允许访问
Person newP=(Person)cons.newInstance("私有的阿反");
System.out.println(newP.toString());
//调用私有方法
Method show=cls.getDeclaredMethod("show");
show.setAccessible(true);//设置允许访问
show.invoke(newP);
//调用私有属性
Field name=cls.getDeclaredField("name");
name.setAccessible(true);//设置允许访问
name.set(newP,"开心的阿反");
System.out.println(newP.toString());
}
通过反射获取属性的性质(权限修饰符 数据类型 变量名)
static void test3() throws Exception {
System.out.println("----------通过反射查询权限修饰符 数据类型 变量名---------");
Class cls = Person.class;
Field [] fs=cls.getDeclaredFields();
for (Field f:fs ){
int modify=f.getModifiers();// 0: default 1:public 2:private
Class classf=f.getType();//获取数据类型
String name=f.getName();//获取变量名
System.out.println(modify+" "+ Modifier.toString(modify) +" "+classf.getName()+ " "+name);
}
}
通过反射获取方法的结构
static void test4() throws Exception {
System.out.println("--m--------通过反射查询类的方法结构---------");
Class cls = Person.class;
//获取运行时类及其所有父类中的public方法
Method [] mm=cls.getMethods();
System.out.println("获取运行时类及其所有父类中的public方法");
for (Method m:mm ) {
System.out.println(m);
}
//获取运行时类声明的所有方法,不包括父类方法
Method [] ms=cls.getDeclaredMethods();
System.out.println();
System.out.println("获取运行时类声明的所有方法的结构,不包括父类方法");
for (Method m:ms ){
int modify=m.getModifiers();// 0: default 1:public 2:private
Class classf=m.getReturnType();//获取返回类型
String name=m.getName();//获取方法名
Class [] paramerType=m.getParameterTypes();//获取参数
String paramers=null;
if (!(paramerType==null && paramerType.length==0)) {
for (Class css : paramerType) {
if (paramers==null){paramers=css.getName();
}else {
paramers = " " + paramers + css.getName();
}
}
}
System.out.println(modify+" "+ Modifier.toString(modify) +" "+classf.getName()+ " "+name+"("+paramers+")");
}
如何看待封装跟反射
它们之间并不矛盾,封装给出的是如何使用的最好提示,而反射是解决能否可以调用,在开发中是可以不按照封装的提示来进行操作的。
注意:在可以直接创建对象的地方尽量不要使用反射创建对象,因为反射往往要到了运行期才能检查出代码错误。