黑马程序员 反射
2015-07-15 16:15
471 查看
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
反射
1、反射的基石:class
字节码:是class的实例对象。
得到字节码方式
1)class.forName
2)类名.class 如Person.class
3)对象.getClass()
isPrimitive()是否是基本类型的字节码
int.class==Integer.TYPE
数组类型的class 实例对象
class.isArray()
总之,只要是在源程序中出现的类型,都有各自的class实例对象。
例如:int[],void
2、反射:就是把java类中的各种成分映射成相应的java类。
3、 Constructor 构造方法
//选择哪个构造方法
Constructor cr1=String.class.getConstructor(StringBuffer.class);//参数可
以多个,如int.class等
//用这个方法时,传一个对象进去
String str2=(String)cr1.newInstance(new StringBuffer("abc"));
//获得方法时要要到类型
有class得到Constructor,再new object
4、Field类:代表某个类中的成员变量
需求:从Demo2.java中获取x,y到Demo1.java
Demo2
private int x;
public int y;
//alt+shift+s
public ReflectPointDemo(int x, int y) {
super();
this.x = x;
this.y = y;
}
Demo1 ReflectPointDemo rpd=new ReflectPointDemo(3, 5);
Field fdy=rpd.getClass().getField("y");
//fdy的值是多少? 5,wrong
//fdy不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值
System.out.println("y="+fdy.get(rpd));
//Field fdx=rpd.getClass().getField("x");//无法获取私有
Field fdx=rpd.getClass().getDeclaredField("x");//获取私有
fdx.setAccessible(true);//强行获取
System.out.println("x="+fdx.get(rpd));
---------
需求:对Demo2.java中s1,s2,s3数据修改,在Demo1.java实现
Demo2.java
public String s1="wang";
public String s2="wei";
public String s3="song";
@Override //请编译器查询
public String toString() {
return s1+":"+s2+":"+s3;
}
Demo1.java
changeStringValue(rpd);//rpd属于上述中的rpd
System.out.println(rpd);
}
public static void changeStringValue(Object obj)throws Exception
{
Field[] fs=obj.getClass().getFields();
for(Field f:fs)
{
//字节码用等号比==,因为这里是同一份字节码
if(f.getType()==String.class){
String oldValue=(String)f.get(obj);
String newValue=oldValue.replace("w", "t");
f.set(obj, newValue);
}
}
5、Method类代表某个类中的一个成员方法
通常方式:System.out.Println(str.charAt(1))
反射方式: System.out.Println(charAt.invoke(str,1))
若传递给Method对象的invoke()方法的第一个参数为null,
那么该Method对象对应的一个静态方法
Demo1.java //调用str2.charAt(1),str2="abc";
Method mdCharAt=String.class.getMethod("charAt", int.class);
System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2, 1));
//jdk1.4的方式
System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2,new Object[]
{2}));
6、 外部函数调用Demo2.java的main函数
用发射的目的:
当不知道执行哪个class时,用这个更适应
通常: Demo2.main(new string{}{"1","2","3"});
//ReflectPointDemo.main(new String[]{"1","2","3"});
String startClassName=args[0];
Method mainMethod=Class.forName(startClassName).getMethod("main",
String[].class);
//mainMethod.invoke(null, new String[]{"1","2","3"});//此时会出现数组下
标越界,会对 new String[]{"1","2","3"}进行拆分
mainMethod.invoke(null,new Object[]{ new String[]{"1","2","3"}});
7、数组的反射:
int[] a1=new int[]{1,2,3};
int[] a2=new int[4];
int[][] a3=new int[2][3];
String[] s4=new String[]{"a","1",","};
System.out.println(a1.getClass()==a2.getClass());//字节码相同
//System.out.println(a1.getClass()==a3.getClass());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(s4.getClass().getSuperclass().getName());
//都是java.lang.Object
//所以能实现
Object obj1=a1;//...
//但是一维int数组无法赋值给Object数组
Object[] ob=a3;
Object[] obs=s4;
System.out.println(a1);//[I@1fb8ee3 哈希口?@1fb8ee3
//于是采用Arrays工具类
System.out.println(Arrays.asList(a1));//[[I@1fb8ee3]
System.out.println(Arrays.asList(s4));//[a, 1, ,]
//数组的反射
printObject(a1);
printObject(s4);
}
public static void printObject(Object obj) {
Class clzz=obj.getClass();
if(clzz.isArray())
{
int len=Array.getLength(obj);
for(int i=0;i<len;i++)
System.out.print(Array.get(obj, i));
System.out.println();
}
}
8、 ArrayList_HashSet的比较及Hashcode分析
hashcode方法与hashSet类
分区域、通过算哈希值找区域,再找目标。提高了效率
hashSet类:去重复的引用
hashcode方法:通过计算哈希值,去等值对象。
练习 public static void main(String[] args) {
// TODO Auto-generated method stub
//Collection cn=new ArrayList();//size=4
Collection cn=new HashSet(); //size=3
ReflectPointDemo rpd =new ReflectPointDemo(3,3);
ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
cn.add(rpd);//将引用添加进去
cn.add(rpd2);
cn.add(rpd3);
cn.add(rpd);//与第一个引用相同
//hashcat若引用相同则无法加入
//若在ReflectPointDemo添加hashCode(),用于去同点 size=2
rpd.y=7;//将rpd存放在其他地方,不被发现 ,使cn.remove(rpd);操作失败,
size=2
cn.remove(rpd);//删除rpd
System.out.println(cn.size());//4
}
ReflectPointDemo 中
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
9、实现框架功能
解决的核心问题:适应性强,时用长(如虚类)
项目->file 取名config.properties
4000
className=java.util.ArrayList //size=4
className=java.util.HashSet //size=2
Demo.java
public static void main(String[] args)throws Exception
{
// TODO Auto-generated method stub
InputStream ips=new FileInputStream("config.properties");
Properties pop=new Properties();
pop.load(ips);
ips.close();//释放资源。
String className=pop.getProperty("className");//前后className不必一样,
但..
Collection cn=(Collection)Class.forName(className).newInstance();
ReflectPointDemo rpd =new ReflectPointDemo(3,3);
ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
cn.add(rpd);//将引用添加进去
cn.add(rpd2);
cn.add(rpd3);
cn.add(rpd);//与第一个引用相同
System.out.println(cn.size());
}
反射
1、反射的基石:class
字节码:是class的实例对象。
得到字节码方式
1)class.forName
2)类名.class 如Person.class
3)对象.getClass()
isPrimitive()是否是基本类型的字节码
int.class==Integer.TYPE
数组类型的class 实例对象
class.isArray()
总之,只要是在源程序中出现的类型,都有各自的class实例对象。
例如:int[],void
2、反射:就是把java类中的各种成分映射成相应的java类。
3、 Constructor 构造方法
//选择哪个构造方法
Constructor cr1=String.class.getConstructor(StringBuffer.class);//参数可
以多个,如int.class等
//用这个方法时,传一个对象进去
String str2=(String)cr1.newInstance(new StringBuffer("abc"));
//获得方法时要要到类型
有class得到Constructor,再new object
4、Field类:代表某个类中的成员变量
需求:从Demo2.java中获取x,y到Demo1.java
Demo2
private int x;
public int y;
//alt+shift+s
public ReflectPointDemo(int x, int y) {
super();
this.x = x;
this.y = y;
}
Demo1 ReflectPointDemo rpd=new ReflectPointDemo(3, 5);
Field fdy=rpd.getClass().getField("y");
//fdy的值是多少? 5,wrong
//fdy不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值
System.out.println("y="+fdy.get(rpd));
//Field fdx=rpd.getClass().getField("x");//无法获取私有
Field fdx=rpd.getClass().getDeclaredField("x");//获取私有
fdx.setAccessible(true);//强行获取
System.out.println("x="+fdx.get(rpd));
---------
需求:对Demo2.java中s1,s2,s3数据修改,在Demo1.java实现
Demo2.java
public String s1="wang";
public String s2="wei";
public String s3="song";
@Override //请编译器查询
public String toString() {
return s1+":"+s2+":"+s3;
}
Demo1.java
changeStringValue(rpd);//rpd属于上述中的rpd
System.out.println(rpd);
}
public static void changeStringValue(Object obj)throws Exception
{
Field[] fs=obj.getClass().getFields();
for(Field f:fs)
{
//字节码用等号比==,因为这里是同一份字节码
if(f.getType()==String.class){
String oldValue=(String)f.get(obj);
String newValue=oldValue.replace("w", "t");
f.set(obj, newValue);
}
}
5、Method类代表某个类中的一个成员方法
通常方式:System.out.Println(str.charAt(1))
反射方式: System.out.Println(charAt.invoke(str,1))
若传递给Method对象的invoke()方法的第一个参数为null,
那么该Method对象对应的一个静态方法
Demo1.java //调用str2.charAt(1),str2="abc";
Method mdCharAt=String.class.getMethod("charAt", int.class);
System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2, 1));
//jdk1.4的方式
System.out.println("str2.charAt(1)="+mdCharAt.invoke(str2,new Object[]
{2}));
6、 外部函数调用Demo2.java的main函数
用发射的目的:
当不知道执行哪个class时,用这个更适应
通常: Demo2.main(new string{}{"1","2","3"});
//ReflectPointDemo.main(new String[]{"1","2","3"});
String startClassName=args[0];
Method mainMethod=Class.forName(startClassName).getMethod("main",
String[].class);
//mainMethod.invoke(null, new String[]{"1","2","3"});//此时会出现数组下
标越界,会对 new String[]{"1","2","3"}进行拆分
mainMethod.invoke(null,new Object[]{ new String[]{"1","2","3"}});
7、数组的反射:
int[] a1=new int[]{1,2,3};
int[] a2=new int[4];
int[][] a3=new int[2][3];
String[] s4=new String[]{"a","1",","};
System.out.println(a1.getClass()==a2.getClass());//字节码相同
//System.out.println(a1.getClass()==a3.getClass());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(s4.getClass().getSuperclass().getName());
//都是java.lang.Object
//所以能实现
Object obj1=a1;//...
//但是一维int数组无法赋值给Object数组
Object[] ob=a3;
Object[] obs=s4;
System.out.println(a1);//[I@1fb8ee3 哈希口?@1fb8ee3
//于是采用Arrays工具类
System.out.println(Arrays.asList(a1));//[[I@1fb8ee3]
System.out.println(Arrays.asList(s4));//[a, 1, ,]
//数组的反射
printObject(a1);
printObject(s4);
}
public static void printObject(Object obj) {
Class clzz=obj.getClass();
if(clzz.isArray())
{
int len=Array.getLength(obj);
for(int i=0;i<len;i++)
System.out.print(Array.get(obj, i));
System.out.println();
}
}
8、 ArrayList_HashSet的比较及Hashcode分析
hashcode方法与hashSet类
分区域、通过算哈希值找区域,再找目标。提高了效率
hashSet类:去重复的引用
hashcode方法:通过计算哈希值,去等值对象。
练习 public static void main(String[] args) {
// TODO Auto-generated method stub
//Collection cn=new ArrayList();//size=4
Collection cn=new HashSet(); //size=3
ReflectPointDemo rpd =new ReflectPointDemo(3,3);
ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
cn.add(rpd);//将引用添加进去
cn.add(rpd2);
cn.add(rpd3);
cn.add(rpd);//与第一个引用相同
//hashcat若引用相同则无法加入
//若在ReflectPointDemo添加hashCode(),用于去同点 size=2
rpd.y=7;//将rpd存放在其他地方,不被发现 ,使cn.remove(rpd);操作失败,
size=2
cn.remove(rpd);//删除rpd
System.out.println(cn.size());//4
}
ReflectPointDemo 中
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
9、实现框架功能
解决的核心问题:适应性强,时用长(如虚类)
项目->file 取名config.properties
4000
className=java.util.ArrayList //size=4
className=java.util.HashSet //size=2
Demo.java
public static void main(String[] args)throws Exception
{
// TODO Auto-generated method stub
InputStream ips=new FileInputStream("config.properties");
Properties pop=new Properties();
pop.load(ips);
ips.close();//释放资源。
String className=pop.getProperty("className");//前后className不必一样,
但..
Collection cn=(Collection)Class.forName(className).newInstance();
ReflectPointDemo rpd =new ReflectPointDemo(3,3);
ReflectPointDemo rpd2=new ReflectPointDemo(4,4);
ReflectPointDemo rpd3=new ReflectPointDemo(3,3);
cn.add(rpd);//将引用添加进去
cn.add(rpd2);
cn.add(rpd3);
cn.add(rpd);//与第一个引用相同
System.out.println(cn.size());
}
相关文章推荐
- 火车上看得面试题
- 黑马程序员_基础语法笔记
- 黑马程序员_Java概述笔记
- 【.Net码农】RDLC 在VS2012后的版本中做数据报表时,提示尚未指定报表“Report1”的报表定义
- 阿里巴巴电话面试2015/7/15
- 黑马程序员——Java基础---io流
- 求职简历怎么写,看看百度吐槽
- windbg相关(阿里巴巴电话面试总结)
- (剑指Offer)面试题17:合并两个排序的链表
- 搜的面试题零散记录
- 15个高级Java多线程面试题及回答
- 阿里电话面试笔记
- 面试,一个不对等的双选之路
- 第一次面试大数据实习生
- 码农职业心理总结
- 面试题:sql实现,根据table1,table2得出table3
- (剑指Offer)面试题16:反转链表
- “程序员”学哪种编程语言最赚钱?
- 黑马程序员--Foundation
- 黑马程序员--IOS基础第十八天(OC)