如果我们把类看成制造一样事物的图纸把对象看成某种具体的事物那么
如果要使用对象的属性方法等东西就有了两种方法:
1是将这个对象制造出来 然后再调用
2是将这个对象的图纸拿到手 然后对照图纸 指定某对象来使用其图纸上面的东西
第二种方法就是反射
如果用图形来表示:
---à对象
--à图纸--à对象(这就是反射)
看起来像相当于多了拿到图纸这一个步骤就像光反射了一下才到达目的地一样所以叫反射
作为反射的基础主要有以下内容:
9种基本类型+数组+集合
构造+属性+方法
最后就是小框架的演习
/*
需求:
演习反射和框架基础的全部内容
9种基本类型+数组+集合
构造+属性+方法
最后就是小框架的演习
*/
import java.util.*;
import java.io.*;
import java.lang.reflect.*;
class ReflectionPoint
{
publicstatic void main(String[] args) throws Exception
{
Stringstr1 = "moriarty";
//三种拿到字节码文件的方式
Classcls1 = str1.getClass();
Classcls2 = String.class;
Classcls3 = Class.forName("java.lang.String"); //注意这个要写类的全名 导包不管用
//同一份字节码文件
sop(cls1== cls2);
sop(cls2== cls3);
//String不是基本类型
sop(cls1.isPrimitive());
//int是基本类型
sop(int.class.isPrimitive());
//int跟Integer不一样
sop(int.class== Integer.class);
//int跟Integer的TYPE一样
sop(int.class== Integer.TYPE);
//数组不属于基本类型
sop(int[].class.isPrimitive());
//数组属于数组
sop(int[].class.isArray());
/*
Constructor<T>getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
*/
//通过反射拿到String类的构造函数
Constructorconstructor1 = String.class.getConstructor(StringBuffer.class);
//通过反射建立String对象
Stringstr2 = (String)constructor1.newInstance(new StringBuffer("fantizi"));
//从对象中调用方法
sop(str2.charAt(2));
//通过反射的方式拿到成员变量(但其实还是先新建了对象)
MyRectanglemr = new MyRectangle(4,5);
//拿到私有成员变量 首先要使用getDeclaredField
Fieldfield1 = mr.getClass().getDeclaredField("y");
//然后还要讲field变量setAccessible(true)
field1.setAccessible(true);
sop(field1.get(mr));
//将所有String类型的成员变量里的b换成a 使用反射
MyRectanglemr2 = new MyRectangle(5,5);
changeStringValue(mr2);
sop(mr2.str1+mr2.str2+mr2.str3);
//使用成员方法的反射 完成charAt的调用
MethodcharAtMethod = String.class.getMethod("charAt",int.class);
sop(charAtMethod.invoke(str1,2));//这里的str1是最开始定义的"moriarty"
sop(charAtMethod.invoke(str1,newObject[]{2}));
//对接受数组参数的成员方法进行反射
//说白了 也就是main方法里面的参数(数组参数) 也就是对main方法进行反射
String startingClassName = args[0];
MethodmainMethod =
Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null,newObject[]{new String[]{"1ab","adfasd"}});
TestArgumentsta = new TestArguments();
Classxxx = ta.getClass();
sop(xxx.getName());
//注意编译的时候 javaReflectionPoint TestArguments
//数组与Object的关系与反射类型
int[]a1 = new int[]{1,2,3};
int[]a2 = new int[4];
int[][]a3 = new int[][]{{1,2,3},{3,4,6}};
String[]a4 = new String[]{"a","b","c","d"};
sop(a1.getClass()== a2.getClass());
//编译错误:不可比较的类型
// sop(a1.getClass()== a3.getClass());
// sop(a1.getClass()== a4.getClass());
sop(a1.getClass().getName());
sop(a2.getClass().getSuperclass().getName());
sop(a4.getClass().getSuperclass().getName());
//学习asList()方法 转换成集合
Objectobj1 = a1;
Objectobj2 = a2;
Object[]obj3 = a3;//重要obj3是二维数组不是一维数组!!!极为重要!
// Object[]obj33 = a1;//基本类型不是Object
Object[]obj4 = a4;
//一维数组和二维数组确实不一样 打印为false
sop(obj1.getClass()== obj3.getClass());
sop(obj1.getClass().getName());
sop(obj3.getClass().getName());
sop(Arrays.asList(a1));
sop(Arrays.asList(a3));
sop(Arrays.asList(a4));
//进化 打印任意维度的数组!
printObject(a3);
Collection<MyRectangle>coll = new HashSet<MyRectangle>();
coll.add(newMyRectangle(3,4));
coll.add(newMyRectangle(7,4));
coll.add(newMyRectangle(1,4));
coll.add(newMyRectangle(1,4));
sop("coll.size()="+coll.size());
//小框架
//配置文件里面需要是HashSet否则无法使用比较
InputStreamin = new FileInputStream("config.properties");
Propertiesprop = new Properties();
prop.load(in);
in.close();
StringclassName = prop.getProperty("className");
Collection<MyRectangle>coll2 =
(HashSet<MyRectangle>)Class.forName(className).newInstance();
coll2.add(newMyRectangle(3,4));
coll2.add(newMyRectangle(7,4));
coll2.add(newMyRectangle(1,4));
coll2.add(newMyRectangle(1,4));
sop("coll2.size()="+coll2.size());
}
//使用迭代 打印任意维度的数组!!
//做出来的关键是:模拟整个过程的运行 不要害怕思考 不要偷懒
publicstatic void printObject(Object obj)
{
Classcls = obj.getClass();
if(cls.isArray())
{
for(int i =0; i<Array.getLength(obj) ; i++)
{
if(Array.get(obj,i).getClass().isArray())
{
printObject(Array.get(obj,i));
}
else
sop(Array.get(obj,i));
}
}
else
sop(obj);
}
publicstatic void changeStringValue(Object obj) throws Exception
{
/*
field对象里面的方法
voidset(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
*/
Field[]f = obj.getClass().getFields();
for( Field field : f )
{
if(field.getType() == String.class)
{
Stringoldvalue = (String)field.get(obj);
Stringnewvalue = oldvalue.replace('b','a');
field.set(obj,newvalue);
}
}
}
publicstatic void sop(Object obj)
{
System.out.println(obj);
}
}
class MyRectangle
{
privateint x,y;
publicString str1 = "ball";
publicString str2 = "basketball";
publicString str3 = "itcast";
publicMyRectangle(int x , int y)
{
this.x= x;
this.y= y;
}
publicint hashCode()
{
intresult = 3;
result= x+result*y;
System.out.println("result="+result);
returnresult;
}
publicboolean equals(Object obj)
{
System.out.println(obj.getClass().getName()+"调用");
if(this == obj)
returntrue;
if(getClass() != obj.getClass())
{
returnfalse;
}
MyRectangleother = (MyRectangle)obj;
if(x != other.x)
{
returnfalse;
}
elseif ( y != other.y)
{
returnfalse;
}
returntrue;
}
}
class TestArguments
{
publicstatic void main(String[] args) throws Exception
{
for(String str : args )
{
System.out.println(str);
}
}
}