——- android培训、java培训、期待与您交流! ———-
Field类
代表某个类中的一个成员变量
问! 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”b“改成”a“
changeSringValue(pt1);//定义一个单独的方法
System.out.println(pt1);
private static void changeSringValue(Object obj) throws Exception {
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
//if(field.getType().equals(String.class))
if(field.getType()==String.class){
String oldValue =(String)field.get(obj);
String newValue =oldValue.replace('b','a');
field.set(obj, newValue);
/*
Method类
代表某个类中的一个成员方法
得到类中的某一个方法;
例子: Method charAt =
Class.forName("java.lang.String").getMethod(”charAt“,int.class);
调用方法:
通常方式;System.out.println(str.chatAt(1));
反射方式:System.out.println(charAt.invoke(str.1));
如果传递给Method对象invoke()方法的一个参数为null,还有这什么样的意义?
说明该Method对象对应的是一个【静态】的方法!
*/
Method methodCharAt = String.class.getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1,1));
/*
反射方式执行某个类中的main方法
目标:
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),
通过反射来调用这个mian 方法时,如何为invoke方法传递参数?
按jdk1.5的语法:
整个数组是一个参数,
按jdk1.4的语法:
数组中的每一个元素对应的一个参数,
当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?
jdk1.5肯定要兼容jdk1.4的语法,会按照,jdk1.4的方法处理,即把数组打散为若干个单独的参数,
所以,在给main参数是,不能使用代码
mainMethod.invoke(null,String[] {"xxx"});
javac只把它当作jdk1.4的语法进行理解,而不是把他当作jdk1.5的语法解释,
因此会出现参数类型不对的问题
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//jkd会拆包,拆完会变成多个单独参数,那给外面在加个包,拆完还是一个数组
mainMethod,invoke(null,(Object)new String[]{"xxx"});//强转成 object 跟编译器说明只有一个对象
编译器会做特殊处理,编译时不把参数当作数组看待,也就不会数组打散若干个参数
*/
TestArguments.main(new String[]{"111","222","333"});
//程序中使用静态代码直接调用main方法
class TestArguments{
public static void main(String[] args){
for(String arg : args){
System.out.println(arg);
//先敲sysout,然后组合快捷键:alt+/,就可以不全代码为:System.out.println();
}
}
}
//为什么? 使用反射的方式调用
// 编写代码时候,不知道 【具体】的类名
String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});//要拆包,那就外面再包一次
//mainMethod.invoke(null, (Object)new String[]{"111","222","333"});//法2 跟编译器说我给的是一个数组不需要拆包
class TestArguments{
public static void main(String[] args){
for(String arg : args){
System.out.println(arg);
//先敲sysout,然后组合快捷键:alt+/,就可以不全代码为:System.out.println();
}
}
}
/*
数组的反射
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I
代表数组的Class实例对象的个体SuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Objcet类型使用,不能当作Object[]类型使用;
非基本类型的一维数组,既可以到做Object类型使用,又可以当作Object[]类型使用
Object[]与String[]没有父子关系,Object与String有父子关系,
所以new Object[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”};
Object x =“abc”能强制转换成String x =“abc”。
Arrays.asList();方法处理int[]和String[]时的差异。
Array 工具类 用于 完成对数组的反射操作
Array.getLength(Object obj);//获取数组的长度
Array.get(Object obj,int x);//获取数组中的元素
如何得到某个数组中的某个元素的类型,
例:
int a = new int[3];Object[] obj=new Object[]{”ABC”,1};
无法得到某个数组的具体类型,只能得到其中某个元素的类型,
如:
Obj[0].getClass().getName()得到的是java.lang.String。
思考题:怎么得到数组中的元素类型?
【占时没有方法,只能得到数组中元素所属的类型,数组的类型是不确定的】
*/
Object obj = null ;
printObject(obj);
}
private static void printObject(Object obj){
Class clazz = obj.geetClass();
if(clazz.isArray()){
int len = Array.getLength(obj);
for (int i = 0;i<len ;i++ )
{
System.out.println(Array.get(obj,i));
}
}
}
/*
HashCode ArrayList 分析
提示
1.通常来说,一个类的2个实例对象用 equals()方法比较的结果相等时,他们的哈希码必须相等
但反之则不成立,即equals()方法比较结果不相等的对象可以有相同的哈希码,或许说哈希姆相同的2个
对象equals()比较方法可以不等,
例如:字符串"BB"和"Aa",的equals()的方法比较结果肯定不相等,但他们hasCode返回的值却相等。
2.当一个对象被存储进HashSet集合中,就不能修改这个对象中的那些【参与计算】哈希值的字段了,
否则,对象修改后的哈希值与最初的存储进HashSet集合中时的哈希值就不同了,这种情况下,即使在
contains方法使用该对象当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的额结果,
这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄漏。
补充
【内存泄露】:某些对象不再使用了,占用着内存空间,并未被释放,就会导致内存泄露;
也就是说当程序不断增加对象,修改对象,删除对象,日积月累,内存就会用光了,就导致【内存溢出】。
*/
package com.itheima;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
public class ReflectTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//Collection collections = new ArrayList();//【未生成 方法之前】数组长度是4 自然数组 有一个放一个
Collection collections = new HashSet();//——————————————————————框架需要修改的地方
//【未生成 方法之前】数组长度是3 有相同的第二个开始就不放了
//【生成之后】数组长都为2,相同的就不再放了
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
//collections.add(new ReflectPoint(3,3));
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}
}
//——————————————————————————————————————————————————
package com.itheima;
public class ReflectPoint {
private int x;
public int y;
public String str1 = "ball";
public String str2 ="basketball";
public String str3 ="itcast";
public ReflectPoint(int x, int y) {//快捷键alt+shift+s ……Fields……
super();
this.x = x;
this.y = y;
}
//右击 source 产生 HasCode代码
@Override
public int hashCode() {//【hashCode方法生成】
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {// 【equals 方法生成】
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
@Override
public String toString(){
return str1 +":"+str2+":"+str3;
}
}
/*
反射的左右——>实现框架功能
框架 与 框架要解决的核心问题
我要做房子卖给住户,有用户自己安装 门窗, 我做的房子就是【框架】,
用户需要使用我的框架,然后把门窗插入到我提供的框架中。
框架与工具类有区别,工具类被【用户的类】调用,而框架则是调用用户提供的类。
框架要解决的核心问题
我在写框架的时候,用户可能不存在,那编写的框架如何调用 后来存在的类呢???
因为编写时候,无法知道要被调用的类名,所以,在程序中无法直接的new某个类的实例对象,
故要使用,反射方法。
*/
Collection collections = new HashSet();//——————————————————————框架需要修改的地方
//HashSet()这里不出现具体的类名,从配置文件中读取
//右击最上javapa 包——New ——File —— config.properties —— className=java.until.ArrayList
config.properties
Source
className=java.until.ArrayList
Collection collections = new HashSet();//——————————————————————框架需要修改的地方
//HashSet()这里不出现具体的类名,从配置文件中读取
//右击最上javapa 包——New ——File —— config.properties —— className=java.until.ArrayList
config.properties
Source
className=java.until.ArrayList
package com.itheima;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
public class ReflectTest2 {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
//Collection collections = new ArrayList();//【未生成 方法之前】数组长度是4 自然数组 有一个放一个
InputStream ips =new FileInputStream("config.properties"); //加载properties文件
Properties props = new Properties();
props.load(ips);
ips.close();//关门
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
//Collection collections = new HashSet();
//【未生成 方法之前】数组长度是3 有相同的第二个开始就不放了
//【生成之后】数组长都为2,相同的就不再放了
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
//collections.add(new ReflectPoint(3,3));
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}
}