------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
反射机制
1.Class 类
在正常情况下,需要现有一个类的完整路径引入之后才能按照固定的格式产生实例化对象,但是在JAVAZ中允许通过一个实例化对象找到一个类的完整信息,这个就是Class类的功能。
理解概念:“一切的操作都将使用Object完成,类、数组的引用都可以使用Object进行接收”。
任何一个类如果没有明确的声明继承自哪个父类时,则默认继承Object类。
在JAVA中Object类是一切类的父类,那么所有类的对象实际上也就都是java.lang.Class类的实例,所以所有的对象都可以转变为java.lang.Class类型表示。
因为Class类中本身没有任何的构造方法,所以得依靠其方法实例化。
实例化Class类对象的方法:
第一种:通过forName()方法
第二种:类.class
第三种:对象.getClass()
样板代码:
package org.lzz.heima ;
class X{
};
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 指定泛型
Class<?> c2 = null ; // 指定泛型
Class<?> c3 = null ; // 指定泛型
try{
// 以下的操作形式是在开发中最常用的一种形式
c1 = Class.forName("org.lzz.heima.X") ;
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
c2 = new X().getClass() ; // 通过Object类中的方法实例化
c3 = X.class ; // 通过类.class实例化
System.out.println("类名称:" + c1.getName()) ; // 得到类的名称
System.out.println("类名称:" + c2.getName()) ; // 得到类的名称
System.out.println("类名称:" + c3.getName()) ; // 得到类的名称
}
}
1.1 用newInstance()方法实例化一个存在无参构造方法的类;
如代码:
package org.lzz.heima ;
class Person{
private String name ; // name属性
private int age ; // 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 ;
}
public String toString(){ // 覆写toString()方法
return "姓名:" + this.name + ",年龄:" + this.age ;
}
};
public class Test{
public static void main(String args[]){
Class<?> c = null ; // 声明Class对象
try{
c = Class.forName("org.lzz.heima.Person") ;
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Person per = null ; // 声明Person对象
try{
per = (Person)c.newInstance() ; // 实例化对象
}catch(Exception e){
e.printStackTrace() ;
}
per.setName("张三") ; // 设置姓名
per.setAge(30) ; // 设置年龄
System.out.println(per) ; // 内容输出,调用toString()
}
}
1.2 调用有参构造实例化对象:
操作步骤:
l 通过Class类中的getConstructors()方法取得本类中的全部构造方法。
l 向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。
l 之后通过Constructor实例化对象。
Constructor 的一些常用方法:
||-得到构造方法的修饰符:Public int getModifiers()
||-得到构造方法的名称: Public String getName()
||-得到次构造方法的信息:public String toSring()
如何调用类中的有参构造:
package org.lzz.heima ;
import java.lang.reflect.Constructor ; // 导入反射机制包
class Person{
private String name ; // name属性
private int age ; // age属性
public Person(String name,int age){
this.setName(name) ;
this.setAge(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 ;
}
public String toString(){ // 覆写toString()方法
return "姓名:" + this.name + ",年龄:" + this.age ;
}
};
public class Test{
public static void main(String args[]){
Class<?> c = null ; // 声明Class对象
try{
c = Class.forName("org.lzz.heima.Person") ;
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Person per1 = null ; // 声明Person对象
Person per2 = null ; // 声明Person对象
Constructor<?> cons[] = null ;
cons = c.getConstructors() ;
try{
per1 = (Person)cons[0].newInstance("张三",30) ; // 实例化对象
per2 = (Person)cons[0].newInstance("李四",25) ; // 实例化对象
}catch(Exception e){
e.printStackTrace() ;
}
System.out.println(per1) ; // 内容输出,调用toString()
System.out.println(per2) ; // 内容输出,调用toString()
}
}
2、取得类的结构:
通过反射得到一个类的完整结构,得使用到java.lang.reflect包中的以下几个类:
l Constructor:表示类中的构造方法。
l Field: 表示类中的属性。
l Method: 表示类中的方法
定义一个测试类 Person.java 和 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 ;
}
};
2.1 取得所实现的全部接口:
使用 getInterfaces() 方法
测试:
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Class<?> c[] = c1.getInterfaces() ; // 以数组形式返回实现的全部接口
for(int i=0;i<c.length;i++){
System.out.println("实现的接口名称:" + c[i].getName()) ; // 输出接口名称
}
}
}
2.2取得父类:
使用 getSuperclass()方法
测试:
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Class<?> c2 = c1.getSuperclass() ; // 取得父类
System.out.println("父类名称:" + c2.getName()) ;
}
}
Object是一切类的父类
2.3取得全部构造方法:
使用 getConstructors()方法
测试:
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造
for(int i=0;i<con.length;i++){
System.out.println("构造方法:" + con[i]) ; // 输出构造,直接打印
}
}
}
2.4取得全部方法:
使用getMothods()方法
测试:
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Method m[] = c1.getMethods() ; // 取得全部方法
for(int i=0;i<m.length;i++){
Class<?> r = m[i].getReturnType() ; // 得到返回值类型
Class<?> p[] = m[i].getParameterTypes() ; // 取得全部参数的类型
int xx = m[i].getModifiers() ; // 得到修饰符
System.out.print(Modifier.toString(xx) + " ") ; // 输出修饰符
System.out.print(r + " ") ;
System.out.print(m[i].getName()) ;
System.out.print("(") ;
for(int j=0;j<p.length;j++){
System.out.print(p[j].getName() + " " + "arg" + j) ;
if(j<p.length-1){
System.out.print(",") ;
}
}
Class<?> ex[] = m[i].getExceptionTypes() ; // 取出异常
if(ex.length>0){
System.out.print(") throws ") ;
}else{
System.out.print(")") ;
}
for(int j=0;j<ex.length;j++){
System.out.print(ex[j].getName()) ;
if(j<p.length-1){
System.out.print(",") ;
}
}
System.out.println() ;
}
}
}
2.5取得全部属性
在反射操作中可以取得一个类中的全部属性,但是在取得属性时有以下两种不同的操作:
l 得到实现的接口或父类的公共属性:public Field[] getFields throws SecurityException.
l 得到本类中的全部属性:public Field[] getDeclaredFields() throws SecurityException
以上方法返回的都是Field的数据,每一个Field对象表示类中的一个属性,而要想获得属性的信息,需要使用的一些方法:
||-得到一个对象中的具体内容:public Object get(Object obj)throws IllegalArgument Exception,IllegalAccessException
||-设置指定对象中属性的具体内容:public void set(Object obj,Object value) throws IllegalArgument Exception,IllegalAccessException
||-得到属性的修饰符:Public int getModifiers()
||-返回次属性的名字:public String getName();
测试:
public class Test{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("org.lzz.heima.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
{ // 本类属性
Field f[] = c1.getDeclaredFields() ; // 取得本类中的属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType() ; // 得到属性类型
int mo = f[i].getModifiers() ; // 得到修饰符的数字
String priv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("本类属性:") ;
System.out.print(priv + " ") ;
System.out.print(r.getName() + " ") ; // 得到属性类型
System.out.print(f[i].getName()) ; // 输出属性名称
System.out.println(" ;") ;
}
}
{ // 公共属性
Field f[] = c1.getFields() ; // 取得本类中的公共属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType() ; // 得到属性类型
int mo = f[i].getModifiers() ; // 得到修饰符的数字
String priv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("公共属性:") ;
System.out.print(priv + " ") ;
System.out.print(r.getName() + " ") ; // 得到属性类型
System.out.print(f[i].getName()) ; // 输出属性名称
System.out.println(" ;") ;
}
}
}
}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------