反射:
什么是反射?有什么用?
先了解一些基本的概念:运行时,编译时,编译型,解释型,类加载器,动态加载类
什么是编译?将原程序翻译成计算机语言,就是二进制代码,在java中是将.java文件也就是源程序翻译成.class的字节码
什么是编译时?将原程序翻译成计算机语言的过程中,将.java翻译为.class文件的过程
什么是运行时?就是在启动这个程序的时候,在java中是,类加载器加载.class文件,并交给jvm处理
什么是编译型语言?将原程序一次性全部转换为二进制代码,然后执行程序
什么是解释型语言?转换一句,执行一句,java是既编译又解释的语言
编译型语言和解释型语言的区别:编译型语言效率高,依赖于编译器,但是跨平台差,解释型的效率低,依赖于解释器,但跨平台强
什么是类加载器?类加载器就是JVM中的类装载器,作用就是将编译好的.class字节码运到检查器进行安全检查的,检查通过后开始解释执行
什么是运行时动态加载类?
反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的
它就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且可以动态的修改这些信息,自己能看到自己,跟照镜子一样,class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等
反射的作用第一,远程方法调用,第二,通过容器得到组件的对象
如何实现反射呢?
得到Class对象
三种方式得到Class对象:
1.调用对象的getClass方法,返回该对象的Class对象
2.Class.forName(“类的名字”);有个受查异常
3.Class c=类名.class
/**
* 知识点:
* Class类
* 知道一个类的对象的名字,就能得到该对象所在类的信息
* 对象.getClass(); getClass()方法是在Object类中定义的
* 程序目标:
* 创建一个对象,得到它的类的信息,如:类名,父类是谁等等
*/
package MY.module12.Class.t1;
public class ClassDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="hello world";
Class c=s.getClass();
System.out.println("类的名字为:"+c.getName());
System.out.println("是否为接口类型:"+c.isInterface());
System.out.println("是否为数组类型:"+c.isArray());
System.out.println("是否为基本类型:"+c.isPrimitive());
System.out.println("父类的名字为:"+c.getSuperclass().getName());
}
}
/**
* 知识点:
* 类被加载的情况
* 当真正使用一个类的时候,该类才会被加载,也就是实例一个对象的时候
* 程序目标:
* 测试什么时候类被加载
*/
package MY.module12.Class.t2;
public class LodaClassTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestClass test=null;
System.out.println("声明个TestClass类的引用");
test=new TestClass();
System.out.println("生成TestClass实例");
}
}
package MY.module12.Class.t2;
public class TestClass {
static{
System.out.println("类被载入");
}
}
/**
* 知识点:
* 得到class对象的三种方式
* Java文件说明:
* Student.java
* TestClass.java
* 程序目标:
* 使用三种方式得到class对象,并且通过class对象得到一个实例
*/
package MY.module12.reflection.Class.t3;
public class TestClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Student stu1=new Student();
//得到class对象的三种方式
//第一种
Class c1=stu1.getClass();
//第二种
try {
Class c2=Class.forName("MY.module12.reflection.Class.t3.Student");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//第三种
Class c3=Student.class;
//使用class对象能做什么呢?
//可以得到该类的一个实例
try {
Student stu2=(Student)c3.newInstance();
System.out.println(stu2);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package MY.module12.reflection.Class.t3;
public class Student {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
StringBuffer sb=new StringBuffer();
sb.append(name+":");
sb.append(age);
return sb.toString();
}
}
分析类的能力:如何分解它
设置属性:
/**
* 知识点:
* 设置属性
* 程序目标:
* 知道一个类的名字和类中的属性,去设置并得到这个属性的值
*/
package MY.module12.reflection.Field;
import java.lang.reflect.*;
public class TestField {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
Class c=Class.forName("MY.module12.reflection.Field.A");
A a1=(A)c.newInstance();
Field f=c.getField("i");
int i=f.getInt(a1);
System.out.println(i);
f.setInt(a1,20);
int j=f.getInt(a1);
System.out.println(j);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class A{
public int i=1;
}
如果我们不知道类中的属性名和数量,并且都是私有的,应该如何设置属性呢?
/**
* 知识点:
*getDeclaredFields(),getDeclaredField(String s),AccessibleObject.setAccessible(f,true);
* 程序目标:
* 只知道类的名字和属性的类型,设置和得到类中私有属性的值
*/
package MY.module12.reflection.Field;
import java.lang.reflect.*;
public class TestField2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
Class c=Class.forName("MY.module12.reflection.Field.B");
B b=(B)c.newInstance();
Field[] f=c.getDeclaredFields();
AccessibleObject.setAccessible(f,true);
int value=f[0].getInt(b);
System.out.println(value);
f[0].setInt(b,10);
int value2=f[0].getInt(b);
System.out.println(value2);
}
}
class B{
private int i=1;
}
设置方法构造器(带参和不带参的):
/**
* 知识点:
* Method
* 程序目标:
* 知道类名,方法的名字和参数类型,调用该类的方法
*/
package MY.module12.reflection.Method;
import java.lang.reflect.*;
public class TestMethodInvoke {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
Class c=Class.forName("MY.module12.reflection.Method.A");
try {
A a=(A)c.newInstance();
Method m=c.getMethod("f1",new Class[]{int.class});
m.invoke(a,new Object[]{new Integer(10)});
m=c.getMethod("f2",new Class[]{int.class});
m.invoke(null,new Object[]{new Integer(20)});
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class A{
public void f1(int i){
System.out.println("f1:"+i);
}
public static void f2(int i){
System.out.println("f2:"+i);
}
}
/**
* 知识点:
* 实例对象(带参和不带参)Constructor类
* 程序目标:
* 知道一个类的名字和类中构造器的参数,实例化带参和不带参数的对象
*/
package MY.module12.reflection.constructor;
import java.lang.reflect.*;
public class TestConstructor {
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
// TODO Auto-generated method stub
Class c=Class.forName("MY.module12.reflection.constructor.B");
B b1=(B)c.newInstance();//不带参数
//带参数
Class[] can=new Class[]{String.class,int.class};
Constructor constructor=c.getConstructor(can);
B b2=(B)constructor.newInstance(new Object[]{new String("yuchen"),new Integer(23)});
}
}
class B{
public B(){
System.out.println("b.....");
}
public B(String s,int i){
System.out.println(s+":"+i);
}
}
/**
* 知识点:
* getName,Modifier类,getModifiers(),getType(),getDeclaredFields()
* getDeclaredMethod(),getDeclaredConstructors(),getParameterTypes()
* Java文件说明:
* Son.java
* Father.java
* printClassinfo.java
* 程序目标:
* 知道一个类的名字
* 1.显示该类的名字和父类的名字
* 2.打印该类中的所有属性,方法,构造器,其中方法结构:
* 修饰符,返回类型,名字,参数类型
*/
package MY.module12.reflection.printClassinfo;
import java.lang.reflect.*;
public class printClassinfo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Class c=Son.class;
Class superC=c.getSuperclass();
if(superC!=null&&superC!=Object.class){
System.out.println(c.getName()+"是"+superC.getName()+"的子类");
}else{
System.out.println(c.getName());
}
System.out.println("{");
printField(c);
System.out.println();
printConstructor(c);
System.out.println();
printMethod(c);
System.out.println("}");
}
public static void printField(Class c){
Field[] field=c.getDeclaredFields();
for(int i=0;i<field.length;i++){
System.out.print(Modifier.toString(field[i].getModifiers())+" ");
System.out.print(field[i].getType().getName()+" "+field[i].getName());
}
}
public static void printMethod(Class c){
Method[] m=c.getDeclaredMethods();
for(int i=0;i<m.length;i++){
System.out.print(Modifier.toString(m[i].getModifiers())+" ");
Class returns=m[i].getReturnType();
System.out.print(returns.getName()+" "+m[i].getName()+"(");
Class[] type=m[i].getParameterTypes();
for(int j=0;j<type.length;j++){
if(j>0){
System.out.print(",");
}
System.out.print(type[j].getName());
}
System.out.println(")");
}
}
public static void printConstructor(Class c){
Constructor[] cs=c.getDeclaredConstructors();
for(int i=0;i<cs.length;i++){
System.out.print(Modifier.toString(cs[i].getModifiers())+" ");
System.out.print(cs[i].getName()+"(");
Class[] Type=cs[i].getParameterTypes();
for(int j=0;j<Type.length;j++){
if(j>0)
System.out.print(",");
System.out.print(Type[j].getName());
}
System.out.println(");");
}
}
}
package MY.module12.reflection.printClassinfo;
public class Son extends Father{
private String name;
public Son() {
// TODO Auto-generated constructor stub
}
public Son(String name,int i) {
// TODO Auto-generated constructor stub
this.name = name;
}
public void sonf(){
}
public void sonf2(int i,String name){
}
}
package MY.module12.reflection.printClassinfo;
public class Father {
public Father(){
}
public Father(String name){
}
public void f1(){
System.out.println("Father's f1()");
}
}
/**
*知识点:
*反射,读配置文件的工具包类
*java文件说明:
*Greeting.java:接口,有个抽象方法
*GreetingChineslmpl.java:实现接口方法,打印中文
*GreetingEnglishlmpl.java:实现接口,打印英文
*GreetingFactory.java:工厂方法:生产Greeting类型的对象
*ConfigUtil.java:读取配置文件,得到文件中的类信息(类名)
*Test.java:输入配置文件中的名字,得到Greeting对象,调用打印方法
*程序目标:
*用户传个参数
*通过工厂方法得到对象,工厂方法通过配置文件类得到类名,然后工厂
*方法通过反射得到对象,返回给用户
*/
package MY.module12.exec.reflection.greetings;
import java.io.IOException;
public class Test {
public static void test(String name){
Greeting g=null;
try {
g = GreetingFactory.getGreeting(name);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.sayHello();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
test("classname");
}
}
package MY.module12.exec.reflection.greetings;
import java.io.IOException;
import java.util.*;
public class ConfigUtil {
public static String getProperty(String name) throws IOException{
String className=null;
Properties p=new Properties();
p.load(ConfigUtil.class.getClassLoader().getResourceAsStream("MY/module12/exec/reflection/greetings/config.properties"));
className=p.getProperty(name);
return className;
}
}
package MY.module12.exec.reflection.greetings;
public interface Greeting {
public void sayHello();
}
package MY.module12.exec.reflection.greetings;
public class GreetingChineselmpl implements Greeting{
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("你好");
}
}
package MY.module12.exec.reflection.greetings;
public class GreetingEnglishlmpl implements Greeting{
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("hello");
}
}
package MY.module12.exec.reflection.greetings;
import java.io.IOException;
public class GreetingFactory {
public static Greeting getGreeting(String name) throws IOException{
Greeting rst=null;
String className=ConfigUtil.getProperty(name);
try {
Class c=Class.forName(className);
rst=(Greeting)c.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rst;
}
}
config.properties :classname=MY.module12.exec.reflection.greetings.GreetingChineselmpl