----------------------android培训、java培训、期待与您交流! ----------------------
今儿一天过的有点扯淡,啥也没做成,一大早让人给叫出去办事,等我到了地方给他打电话的时候才发现他电话停机。我圈圈叉叉诅咒呢。。。回来的时候想去看看别的朋友吧,人家又不想见我。崩溃了。点儿背。晚上睡觉的时候还让人给开刷。啥事了。算了吧,不想了。整理一下今天看的东西吧,睡觉觉。困得难受。今儿就不列大纲了,等有时间给补上吧。眼睛睁不开了。
1.Person p1 = new Person();
p1.getClasss();//p1代表某个字节码所产生的对象。通过getClass可以得到它所属的字节码。
2.Class.forName(“java.lang.String”);//得到string类的字节码。第一种是这个类的字节码已经加载进内存,不需要再加载,直接找到该字节码并返回。第二种是这个类的 字节码还没有被加载进内存,先使用类加载器将该类加载进内存,将该字节码缓存,并返回得到的字节码。
3.八个基本数据类分别对应8个基本类型的字节码文件。还有一个void。
Class clazz =void.class;
总结一下:任何对象都具有.class属性。
Demo:
Stringstr = “abc”;
Classcls1 = str.getClass(); //得到stri所属的字节码
Classcls2 = String.class(); //得到String类的字节码
Classcls3 = Class.forName(“java.lang.String”);//通过forName得到String类字节码
System.out.print(cls1==cls2);
System.out.print(cls1==cls3);
打印结果两个true,证明了不管通过什么方式得到该类的字节码文件,该字节码文件只有一个。
4. 方法:
a) isPrimitive() 是否是基本数据类型 cls2.isPrimitive();
b) 注意:int.class = Integer.TYPE 这个常量代表了这个包装类所包装的基本数据类型的字节码
c) 判断一个字节码文件是不是数组类型,可以使用isArray()方法.int[].class.isArray().
5. 反射:
a) 构造函数的反射:
i. Constructor类代表字节码文件中的构造方法
ii. Constructor cons =String.class.getConstructor(StringBuffer.class);
1. //剖析:
a) String.class 得到String类的字节码文件
b) getConstructor()得到构造函数
getConstructor( Class<?>... parameterTypes)
c) StringBuffer.class 传入的是对应参数的字节码文件,每一个类型对应的字节码文件都是唯一的。这个stringbuffer表示选择哪个构造器
i.扩展…代表的是可变参数,也就是说可以传入多个参数
d) Constructor 返回的类型是构造函数,所以拿Constructor来接收
扩展:
i.new String(new StringBuffer(“abc”));
1.剖析:
i.new StringBuffer(“abc”) //创建一个匿名对象,它的初始内容是abc。
ii. new String() 创建一个匿名对象,它传入的参数是stringbuffer类型的数据
iii. cons.newInstance(newStringBuffer(“abc”))
1. 剖析
a) 在上边得到了构造函数,使用newInstance()来创建构造函数实例化对象,每调用一次,就相当于创建了一个String对象
b) new StringBuffer(“abc”)传入一个stringbuffer的对象,表示的是使用这个构造方法的时候需要给里边传入一个stringbuffer的对象(详见扩展)
iv.String str =(String)cons.newInstance(new StringBuffer(“abc”));
1. 注意;这里需要强转一下,因为编译器在编译时只认识它是一个构造方法,但是不明确究竟是谁的构造方法,所以这里需要强转明确一下。
v. System.out.print(str.charAt(2)); //返回该参数的第二个位置的数据
整理:整个意思是是先获取到某个类的构造方法,然后通过创建构造方法的实例化对象,通过传入相对应的对象,返回一个值。
b) 成员变量的反射
public class ReflectPoint {
//申明两个变量,对X,Y进行反射
private int x;
public int y;
//构造函数
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
public static void main(String[]args) throws SecurityException, NoSuchFieldException {
ReflectPoint pt1 =new ReflectPoint(3, 5);
//创建一个对象,对其进行默认赋值
Field fildy =pt1.getClass().getField("y");
//根据变量名,返回一个类中的公共的成员变量,此时fildy只代表一个变量 ,而不是一个值
System.out.print(fildy.get(pt1));
//这时才是获取成员变量y的值.这里需要明确的是它是属于哪个对象的变量。
Field fieldX =pt1.getClass().getDeclaredField(“x”);
//获取私有成员变量
fieldX.setAccessible(true);
//暴力访问.
System.out.print(fieldX.get(pt1));
}
开发应用:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”变成“a”
public class ReflectPoint {
//申明两个变量,对X,Y进行反射
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "fdbas";
//构造函数
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
//复写toString方法
@Override
public String toString(){
return "ReflectPoint [ str1=" + str1
+ ", str2=" + str2 + ", str3=" + str3 + "]";
}
}
//字符串转换
public static void changeStringValue(Object obj) throwsIllegalArgumentException, IllegalAccessException {
// TODO Auto-generatedmethod stub
//得到该类中的所有的成员变量
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
//因为字节码只有一份,所以直接使用双等号
//判断变量的类型是否是String类型
if(field.getType()==(String.class)){
//取值
String oldValue =(String)field.get(obj);
//使用字符串替换功能
String newValue = oldValue.replace('b', 'a');
//将原值替换成新值
field.set(obj, newValue);
}
}
}
//打印
System.out.println(pt1);
changeStringValue(pt1);
System.out.println(pt1);
c) 成员函数的反射:
i. Method类
public static void getShow(Objectobj) throws Exception {
Method method = obj.getClass().getMethod("show", int.class);
method.invoke(null, 10);//代表了它调用的是一个静态方法
method.invoke(obj,10); //代表了它调用哪个类里边的函数
}
为什么使用反射调用?
因为源程序中不知道究竟要执行哪个类.
/*
* 写一个程序,这个程序根据用户提供的类名,去执行该类中的main方法
*/
public static void main(String[]args) throws SecurityException, NoSuchMethodException, Exception {
// TODO Auto-generated method stub
StringstartClassInfo = args[0]; //假设传入的参数第一个是类名
Method method= Class.forName(startClassInfo).getMethod("main", String[].class);
//method.invoke(null, (Object)newString[]{"12","34","432"});//因为string[]也属于object类型
method.invoke(null, new Object[]{new String[]{"12","34","432"}});
//将其封装成Object数组类型的对象,成为一个整体传入.其原因是为了兼容jdk1.4
}
}
class TestArguments{
public static void main(String[]args) {
for(String arg :args){
System.out.println(arg);
}
}
}
数组与object的关系:
int[] a1 = new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[3];
System.out.println(a1.getClass() == a2.getClass());
//因为是对象,必须使用方法来获取当前对饮的字节码文件 true
System.out.println(a1.getClass().equals(a3.getClass()));//false
System.out.println(a1.getClass().equals(a4.getClass()));
System.out.println(a1.getClass().getSuperclass().getName()); //[I
System.out.println(a2.getClass().getSuperclass().getName());
System.out.println(a3.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
//4个打印输出的结果都是Object
}
Object[] obj = a1;//错误,基本数据类型的一维数组不能够转换为Object数组类型
//结论:除基本类型以外的类型 任何对象的父类都是Object。
基本数据类型不是object
----------------------android培训、java培训、期待与您交流! ----------------------