黑马程序员——JAVA学习笔记——反射机制(下)
2015-03-23 23:00
477 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
反射机制的深入应用
反射除了可以取得一个类的完整结构外,还可以调用类中的指定方法或指定属性,并且可以通过反射完成对数组的操作。
1、 通过反射调用类中的方法:
使用Method类完成
操作步骤:
(1)通过Class 类的getMethod(String name,Class…parameterTypes)方法取得一个Method的对象,并设置次方法操作时所需要的参数类型。
(2)之后可以使用invoke()进行调用。并向方法中传递要设置的参数。
样板代码:定义一个Person类和China接口测试
package org.lzz.heima ;
interface China{ // 定义China接口
public static final String NATIONAL = "China" ; // 定义全局常量
public static final String AUTHOR = "welcome!" ; // 定义全局常量
public void sayChina() ; // 无参的,没有返回值的方法
public String sayHello(String name,int age) ; // 定义有两个参数的方法,并返回内容
}
public class Person implements China{
private String name ;
private int age ;
public Person(){ // 无参构造
}
public Person(String name){
this.name = name ; // 设置name属性
}
public Person(String name,int age){
this(name) ;
this.age = age ;
}
public void sayChina(){ // 覆写方法
System.out.println( AUTHOR + NATIONAL) ;
}
public String sayHello(String name,int age){
return name + ",你好!我今年:" + age + "岁了!" ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
};
运用一:调用Person类中的sayChina()方法
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayChina") ; // 找到sayChina()方法
met.invoke(c1.newInstance()) ; // 调用方法
}catch(Exception e){
e.printStackTrace() ;
}
}
};
运用二:调用Person类中的sayHello 方法
此方法中存在两个参数
采用如下格式:Method met = c1.getMethod("sayHello",String.class,int.class) ;
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"张三",30) ;
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayHello",String.class,int.class) ; // 找到sayChina()方法
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"张三",30) ; // 调用方法
System.out.println(rv) ;
}catch(Exception e){
e.printStackTrace() ;
}
}
};
运用三:调用setter及getter方法
实现步骤:
(1)设置方法名,因为Person类中方法名为:setName(),getName(),setAge(),getAge()
其中属性的的首个字母大写了,所以单独设置一个initStr()方法解决。
(2)调用setter()方法,为满足getMethod()和invoke()方法的使用要求,传入实例化对象、要操作的属性名字、要设置的参数内容以及具体的参数类型。
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
Object obj = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
obj = c1.newInstance() ;
}catch(Exception e){}
setter(obj,"name","张三",String.class) ; // 调用setter方法
setter(obj,"age",30,int.class) ; // 调用setter方法
System.out.print("姓名:") ;
getter(obj,"name") ;
System.out.print("年龄:") ;
getter(obj,"age");
}
/**
Object obj:要操作的对象
String att:要操作的属性
Object value:要设置的属性内容
Class<?> type:要设置的属性类型
*/
public static void setter(Object obj,String att,Object value,Class<?> type){
try{
Method met = obj.getClass().getMethod("set"+initStr(att),type) ; // 得到setter方法
met.invoke(obj,value) ; // 设置setter的内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static void getter(Object obj,String att){
try{
Method met = obj.getClass().getMethod("get"+initStr(att)) ; // 得到setter方法
System.out.println(met.invoke(obj)) ; // 调用getter取得内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static String initStr(String old){ // 将单词的首字母大写
String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
return str ;
}
};
运用四:通过反射操作属性
操作步骤:
(1) 通过Field类操作类中的属性,通过Field类提供的set()和get()方法完成设置和取得属性内容的操作。
(2) 使用Field类中的setAccessibel(true)方法将操作的属性设置成可以被外部访问。(因为Field类中的所有属性全部设置成了私有权限)
public class Test{
public static void main(String args[]) throws Exception{
Class<?> c1 = null ;
Object obj = null ;
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
obj = c1.newInstance() ;
Field nameField = null ;
Field ageField = null ;
nameField = c1.getDeclaredField("name") ; // 取得name属性
ageField = c1.getDeclaredField("age") ; // 取得name属性
nameField.setAccessible(true) ; // 此属性对外部可见
ageField.setAccessible(true) ; // 此属性对外部可见
nameField.set(obj,"张三") ; // 设置name属性内容
ageField.set(obj,30) ; // 设置age属性内容
System.out.println("姓名:" + nameField.get(obj)) ;
System.out.println("--------");
System.out.println("年龄:" + ageField.get(obj)) ;
}
};
2、 通过反射操作数组:
反射机制不仅可以用在类上,还可以应用在任意的引用数据类型的数据上。
可以同过Class类中的方法取得一个数组的Class对象:
public Class<?>getComponentType()
了解数组类\Array的一些常用方法:
||-根据下标去的具体内容:public static Object get(Object array,int index)throws Illegal ArgumentException,ArrayIndexOutBoundsException
||-根据已有的数组类型开辟新的数组对象:Public static Object newInstance(Class<?>componentType,int length)throws NegativeArraySizeException
||-修改指定位置的内容; public static void set(Object array,int index,Object value)throws IllegalArgumentException,ArrayIndexOutOfBoudsException
运用一:取得数组信息并修改数组的内容
import java.lang.reflect.Array ;
public class Test{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
Class<?> c = temp.getClass().getComponentType() ; // 取得数组的Class对象
System.out.println("类型:" + c.getName()) ; // 取得数组类型名称
System.out.println("长度:" + Array.getLength(temp)) ;
System.out.println("第一个内容:" + Array.get(temp,0)) ;
Array.set(temp,0,6) ;
System.out.println("第一个内容:" + Array.get(temp,0)) ;
}
};
运用二:修改数组的大小
import java.lang.reflect.Array ;
public class Test{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
int newTemp[] = (int []) arrayInc(temp,5) ; // 重新开辟空间5
print(newTemp) ;
System.out.println("\n-------------------------") ;
String t[] = {"lzz","cscd","csdnjava"} ;
String nt[] = (String [])arrayInc(t,8) ;
print(nt) ;
}
public static Object arrayInc(Object obj,int len){
Class<?> c = obj.getClass() ;
Class<?> arr = c.getComponentType() ; // 得到数组的
Object newO = Array.newInstance(arr,len) ; // 开辟新的大小
int co = Array.getLength(obj) ;
System.arraycopy(obj,0,newO,0,co) ; // 拷贝内容
return newO ;
}
public static void print(Object obj){ // 数组输出
Class<?> c = obj.getClass() ;
if(!c.isArray()){ // 判断是否是数组
return;
}
Class<?> arr = c.getComponentType() ;
System.out.println(arr.getName()+"数组的长度是:" + Array.getLength(obj)) ; // 输出数组信息
for(int i=0;i<Array.getLength(obj);i++){
System.out.print(Array.get(obj,i) + "、") ; // 通过Array输出
}
}
};
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
反射机制的深入应用
反射除了可以取得一个类的完整结构外,还可以调用类中的指定方法或指定属性,并且可以通过反射完成对数组的操作。
1、 通过反射调用类中的方法:
使用Method类完成
操作步骤:
(1)通过Class 类的getMethod(String name,Class…parameterTypes)方法取得一个Method的对象,并设置次方法操作时所需要的参数类型。
(2)之后可以使用invoke()进行调用。并向方法中传递要设置的参数。
样板代码:定义一个Person类和China接口测试
package org.lzz.heima ;
interface China{ // 定义China接口
public static final String NATIONAL = "China" ; // 定义全局常量
public static final String AUTHOR = "welcome!" ; // 定义全局常量
public void sayChina() ; // 无参的,没有返回值的方法
public String sayHello(String name,int age) ; // 定义有两个参数的方法,并返回内容
}
public class Person implements China{
private String name ;
private int age ;
public Person(){ // 无参构造
}
public Person(String name){
this.name = name ; // 设置name属性
}
public Person(String name,int age){
this(name) ;
this.age = age ;
}
public void sayChina(){ // 覆写方法
System.out.println( AUTHOR + NATIONAL) ;
}
public String sayHello(String name,int age){
return name + ",你好!我今年:" + age + "岁了!" ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
};
运用一:调用Person类中的sayChina()方法
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayChina") ; // 找到sayChina()方法
met.invoke(c1.newInstance()) ; // 调用方法
}catch(Exception e){
e.printStackTrace() ;
}
}
};
运用二:调用Person类中的sayHello 方法
此方法中存在两个参数
采用如下格式:Method met = c1.getMethod("sayHello",String.class,int.class) ;
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"张三",30) ;
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
Method met = c1.getMethod("sayHello",String.class,int.class) ; // 找到sayChina()方法
String rv = null ;
rv = (String)met.invoke(c1.newInstance(),"张三",30) ; // 调用方法
System.out.println(rv) ;
}catch(Exception e){
e.printStackTrace() ;
}
}
};
运用三:调用setter及getter方法
实现步骤:
(1)设置方法名,因为Person类中方法名为:setName(),getName(),setAge(),getAge()
其中属性的的首个字母大写了,所以单独设置一个initStr()方法解决。
(2)调用setter()方法,为满足getMethod()和invoke()方法的使用要求,传入实例化对象、要操作的属性名字、要设置的参数内容以及具体的参数类型。
public class Test{
public static void main(String args[]){
Class<?> c1 = null ;
Object obj = null ;
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
}catch(Exception e){}
try{
obj = c1.newInstance() ;
}catch(Exception e){}
setter(obj,"name","张三",String.class) ; // 调用setter方法
setter(obj,"age",30,int.class) ; // 调用setter方法
System.out.print("姓名:") ;
getter(obj,"name") ;
System.out.print("年龄:") ;
getter(obj,"age");
}
/**
Object obj:要操作的对象
String att:要操作的属性
Object value:要设置的属性内容
Class<?> type:要设置的属性类型
*/
public static void setter(Object obj,String att,Object value,Class<?> type){
try{
Method met = obj.getClass().getMethod("set"+initStr(att),type) ; // 得到setter方法
met.invoke(obj,value) ; // 设置setter的内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static void getter(Object obj,String att){
try{
Method met = obj.getClass().getMethod("get"+initStr(att)) ; // 得到setter方法
System.out.println(met.invoke(obj)) ; // 调用getter取得内容
}catch(Exception e){
e.printStackTrace() ;
}
}
public static String initStr(String old){ // 将单词的首字母大写
String str = old.substring(0,1).toUpperCase() + old.substring(1) ;
return str ;
}
};
运用四:通过反射操作属性
操作步骤:
(1) 通过Field类操作类中的属性,通过Field类提供的set()和get()方法完成设置和取得属性内容的操作。
(2) 使用Field类中的setAccessibel(true)方法将操作的属性设置成可以被外部访问。(因为Field类中的所有属性全部设置成了私有权限)
public class Test{
public static void main(String args[]) throws Exception{
Class<?> c1 = null ;
Object obj = null ;
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化Class对象
obj = c1.newInstance() ;
Field nameField = null ;
Field ageField = null ;
nameField = c1.getDeclaredField("name") ; // 取得name属性
ageField = c1.getDeclaredField("age") ; // 取得name属性
nameField.setAccessible(true) ; // 此属性对外部可见
ageField.setAccessible(true) ; // 此属性对外部可见
nameField.set(obj,"张三") ; // 设置name属性内容
ageField.set(obj,30) ; // 设置age属性内容
System.out.println("姓名:" + nameField.get(obj)) ;
System.out.println("--------");
System.out.println("年龄:" + ageField.get(obj)) ;
}
};
2、 通过反射操作数组:
反射机制不仅可以用在类上,还可以应用在任意的引用数据类型的数据上。
可以同过Class类中的方法取得一个数组的Class对象:
public Class<?>getComponentType()
了解数组类\Array的一些常用方法:
||-根据下标去的具体内容:public static Object get(Object array,int index)throws Illegal ArgumentException,ArrayIndexOutBoundsException
||-根据已有的数组类型开辟新的数组对象:Public static Object newInstance(Class<?>componentType,int length)throws NegativeArraySizeException
||-修改指定位置的内容; public static void set(Object array,int index,Object value)throws IllegalArgumentException,ArrayIndexOutOfBoudsException
运用一:取得数组信息并修改数组的内容
import java.lang.reflect.Array ;
public class Test{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
Class<?> c = temp.getClass().getComponentType() ; // 取得数组的Class对象
System.out.println("类型:" + c.getName()) ; // 取得数组类型名称
System.out.println("长度:" + Array.getLength(temp)) ;
System.out.println("第一个内容:" + Array.get(temp,0)) ;
Array.set(temp,0,6) ;
System.out.println("第一个内容:" + Array.get(temp,0)) ;
}
};
运用二:修改数组的大小
import java.lang.reflect.Array ;
public class Test{
public static void main(String args[]) throws Exception{
int temp[] = {1,2,3} ;// 声明一整型数组
int newTemp[] = (int []) arrayInc(temp,5) ; // 重新开辟空间5
print(newTemp) ;
System.out.println("\n-------------------------") ;
String t[] = {"lzz","cscd","csdnjava"} ;
String nt[] = (String [])arrayInc(t,8) ;
print(nt) ;
}
public static Object arrayInc(Object obj,int len){
Class<?> c = obj.getClass() ;
Class<?> arr = c.getComponentType() ; // 得到数组的
Object newO = Array.newInstance(arr,len) ; // 开辟新的大小
int co = Array.getLength(obj) ;
System.arraycopy(obj,0,newO,0,co) ; // 拷贝内容
return newO ;
}
public static void print(Object obj){ // 数组输出
Class<?> c = obj.getClass() ;
if(!c.isArray()){ // 判断是否是数组
return;
}
Class<?> arr = c.getComponentType() ;
System.out.println(arr.getName()+"数组的长度是:" + Array.getLength(obj)) ; // 输出数组信息
for(int i=0;i<Array.getLength(obj);i++){
System.out.print(Array.get(obj,i) + "、") ; // 通过Array输出
}
}
};
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
相关文章推荐
- 黑马程序员——JAVA学习笔记——反射机制(上)
- 黑马程序员学习笔记之八(Java 反射机制)
- 黑马程序员——java学习笔记--反射机制
- 黑马程序员 java学习笔记 Day11:反射机制详解
- 黑马程序员—Java基础加强学习笔记之枚举&反射
- 黑马程序员_JAVA反射学习笔记
- 【Java学习笔记】-----反射机制
- Java 反射机制-学习笔记
- 黑马程序员 java学习笔记——反射
- 黑马程序员--反射机制和类加载器--java学习日记12(高新技术)
- 15. JAVA 反射机制 Part 1(Class类、反射、反射机制) ----- 学习笔记
- java学习笔记09--反射机制
- java学习笔记09--反射机制
- Java学习笔记之反射机制初探
- 黑马程序员之java类加载器和java中的反射机制学习
- Effective Java 学习笔记(第53条:接口优先于反射机制)
- 黑马程序员--Java基础加强学习笔记之Class类、反射(Reflect)
- java学习笔记---类型信息(type information)、反射机制与动态代理
- 黑马程序员——java 反射学习笔记
- 黑马程序员------java学习笔记之反射