自学javaSE-反射

一、反射概述

1、反射机制中主要掌握的类型:

java.lang.Class;//类整体

java.lang.reflect.Constructor;//构造方法

java.lang.reflect.Field;//属性

java.lang.reflect.Medthod;//方法

java.lang.reflect.Modifier;//修饰符

以上类都可以创建对象

class User{
    String name;
    User(){}
    public void m1(){}
}

反射机制的作用:

​ 1、反编译:.class———》.java

​ 2、通过反射机制访问java类的的属性,方法,构造方法等

二、获取class的三种方式

/*
	获取class类型对象的三种方式
*/
public class ReflectTest01{
    
    public static void main(String args[]) throws Exception{
        //第一种方式
        Class c1  = Class.forName("Employee");//c1引用保存内存地址指向堆中对象,该对象代表的是Employee整个类
        //第二种方式
        //java种每个类型都有class属性
        Class c2 = Employee.class;
        
        //第三种方式
        //java语言中任何一个对象都有getClass方法
        Employee e = new Employee();
        Class c3 = e.getClass();//c3是运行时类,e的运行时类时Employee
        
        //因为Employee这个类在JVM中只有一个,所以c1,c2,c3的内存地址时相同的,指向堆中的一个对象
        System.out.println(c1==c2);//true
        System.out.println(c3==c2);//true
        
        Class c5 = Class.forName("java.util.Data");//必须写全名,类全,名带有包名
        
        Date d = new Date();
        Class c6 = d.getClass();
        
        System.out.println(c4==c5);//true
        System.out.println(c5==c6);//true
        
        //c7代表int类型
        Class c7 = int.class;
        
        
    }
    
}

public class Employee{
    //Filed
    private String name;
    //Constructor
    Employee(){
        
    }
    Employee(String name){
        this.name = name;
    }
    //Medthod
    public void m1(){
        System.out.println(name+" 在工作 ");
    }
    
    
}

三、通过Class类对象创建java对象

public class ReflectTest02{
    
    public static void main(String args[]){
        
        //将A.class文件装载到JVM中的过程
        Class.forName("A");
        
        //不会执行静态语句块
        Class c = A.class;
        
    }
    
}

class A{
    
    static{
        System.out.println("A......");
    }
}
/*
	获取Class类型的对象之后,可以创建该类的对象
*/
import java.util.*;
import java.text.*;
public class ReflectTest03{
    public static void main(String args[]) throw Exception{
        Class c = Class.forName("Employee");
        
        //创建此Class对象所表示类的一个新实例
        Object o = c.newInstance();//调用Employee的无参数构造方法
        
        System.out.println(o);
        
        Class c1 = Class.forName("java.util.Date");
        Object o1 = c1.newInstance();
        
        if(o1 instanceof Date){
            Data t = (Data)o1;
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:ss:mm SSS").format(t));
        }
    }
    
}

四、可变长参数

/*
	关于java中的可变长参数
*/
import java.util.*;
public class Test01{
    
    //m1方法中有一个int类型的可变长参数
    public static void m1(int... a){
        System.out.println("Test");//m1方法调用的时候,传递的参数可以是0-N个
    }
    //如果有精确匹配的方法,则调用该方法,不会再去执行可变长参数的那个方法
    public static void m1(int a){
        System.out.println(a);
    }
    
    //可变长参数可以等同看做数组
    public static void m2(String... args){
        for(int i = 0;i<args.length;i++){
            System.out.println(args[i]);
        }
    }
    
    public static void m3(Class... args) throw Exception{
        for(int i = 0;i<args.length;i++){
            Class c = args[i];
            System.out.println(c.newInstance());
        }
    }
    
    //可变长参数只能出现一次,并且只能出现在所有参数的最后一位
    //public static void m4(String... args,int i){}
    public static void m4(int i,String... args){}
    
    
    public static void main(String[] args) throw Exception{
        m1();
        m1(1);
        m1(1,2);
        m1(1,2,3);
        
        m2("aaa","aaa","aaa","aaa");
        String[] s = {"aaa","aaa","aaa","aaa"};
        m2(s);
        
        m3(Date.class,Employee.class);
    }
    
}

五、IO和Properties的联合应用

/*
	IO + Properties
	
	dbinfo这样的文件我们成为配置文件
	配置文件的作用就是:使程序更加灵活
	
	注意:一般在程序中可变的东西不要写死,推荐写到配置文件中
	运行同样的的程序将得到不同的结果
	
	像dbinfo这样一个具有特殊内容的配置文件我们又叫做属性文件。
	java规范中要求属性文件以“.properties”结尾
	
	属性文件中数据要求:
		key和value之间可以使用空格、冒号、等号
		如果空格、冒号、等号都有,按最前的作为分割符
*/
import java.io.*;
import java.util.*;

public class Test01{
    
    public static void main(String[] args){
        
        //创建属性对象
        Properties p = new Properties();//和Map一样,只不过key和value只能存储字符串
        								//key不能重复,如果重复,后者会覆盖前者
        //创建流
        FileInputStream fis = new FileInputStream("dbinfo.properties");
        
        //将fis流中的所有数据加载到属性对象中
        p.load(fis);//所以现在属性对象p中有了键值对(key=username,value=scott)
        
        //关闭流
        fis.close();
        
        String v1 = p.getProperty("driver");
        String v2 = p.getProperty("url");
        String v3 = p.getProperty("username");//如果读取的是中文,可以先将中文转ascll码再写上去
        String v4 = p.getProperty("password");
        
        System.out.println(v1);
        System.out.println(v2);
        System.out.println(v3);
        System.out.println(v4);
        
        
        
        
    }
    
}

dbinfo.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:3306:bjpowernode
username=zhangsan
password=tiger

六、反射+IO+Properties联合应用,动态创建java对象

import java.io.*;
import java.util.*;

public class Test01{
    
    public static void main(String[] args){
        
        //1、创建属性对象
        Properties p = new Properties();
        
        //2、创建流
        FileReader fr = new FileReader("classInfo.properties");
        
        //3、加载
        p.load(fr);
        
        //4、关闭流
        fr.close();
        
        //通过key获取value
        String className = p.getProperty("className");
        
        //通过反射创建对象
        Class c = Class.forName(className);
        
        //创建对象
        Object o = c.newInstance();
        
        System.out.println(o);
        
    }
    
}

classInfo.properties

className=java.util.Date

七、反编译

public class User{
    //Field
    private String id;
    public int age;
    protected String addr;
    boolean sex;
}

这里反编译类中的属性

/*
	这里反编译类中的属性
	java.lang.reflect.Field;//类中的属性
*/
import java.lang.reflect.*;
public class Test01{
    
    public static void main(String args){
        
        //获取整个类
        Class c = Class.forName("User");
        
        //获取属性Field
        /*
        	//获取所有的public修饰的属性
        	Field[] fs = c.getFields();
        	System.out.println(fs.length);
        	System.out.println(fs[0].getName());
        */
        
        //获取所有的属性
        Field[] fs = c.getDeclareFields();
        
        /*
        	for(Field field:fs){
        		int i = field.getModifiers();
        		//System.out.println(i);
        		String strModifier Modifier.toString(i);
        		System.out.println(strModifier);
        		
        		Class type = field.getType();
        		//System.out.println(type.getName());
        		System.out.println(type.getSimpleName());
        		
        		System.out.println(field.getName());
        	}
        */
        
        StringBuffer sb = new StringBuffer();
        
        sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{\n");
        
        for(Field field:fs){
            sb.append(\t);
            sb.append(Modifier.toString(field.getModifiers()) + " ");
            sb.append(field.getType().getSimpleName() + " ");
            sb.append(field.getName()+";\n");
        }
        sb.append("}");
        
        System.out.println(sb);
    }
    
}

通过反编译获取某个类的具体的某个属性

/*
	通过反编译获取某个类的具体的某个属性
*/
import java.lang.reflect.*;
public class Test02{
    
    public static void main(Stirng[] args) throws Exception{
        
        //以前的方式
        /*
        User u = new User();
        u.age = 12;
        System.out.println(u.age);
        */
        
        //获取类
        Class c = Class.forName("User");
        
        //获取id属性
        Field id = c.getDeclaredField("id");
        
        //创建对象
        Object o = c.newInstance();
        
        //打破封装
        id.setAccessible(true);
        //使用反射机制可以打破分装,但同时也导致了java对象的不安全
        
        //给o对象的id属性赋值“110”
        id.set(o,"110");
        
        //get
        System.out.println(id.get(o));
        
    }
    
}

反编译某个类的所有方法

/*
	反编译某个类的所有方法
*/
import java.lang.reflect.*public class Test03{
    
    public static void main(String[] args) throws Exception{
        
        //获取类
        Class c = Class.forName("java.lang.String");
        
        //获取所有方法
        Method[] ms = c.getDeclareMethods();
        
        for(Method m:ms){
            //修饰符号
            System.out.println(Modifier.toString(m.getModifiers()));
            
            //方法的返回值类型
            Class returnType  = m.getReturnType();
            System.out.println(returnTyipe.getSimpleName());
            
            //方法名
            System.out.println(m.getName());
            
            //方法的形式参数列表
            Class[] p = m.getParameterTypes();
            for(Class p:p){
                System.out.println(p.getSimpleName());
            }
        }
        
    }
    
}

获取某个特定的方法,通过反射机制执行

/*
	获取某个特定的方法,通过反射机制执行
	
	以前:
	Test t = new Test();
	 t.login();
*/
import java.lang.reflect.*;

public class Test04{
    
    public static void main(String[] args) throws Exception{
        
        //获取类
        Class c = Class.forName("CustomerService");
        
        //获取某个特定的方法
        //通过:方法名+形式参数列表
        Method m = c.getDeclaredMethod("login",String.class,String.class);
        
        //通过反射机制执行方法
        Object o = c.newInstance();
        
        Object retValue = m.invoke(o,"admin","123");
        
        System.out.println(retValue);
    }
    
    
}

反编译构造方法

/*
	反编译构造方法
*/
import java.lang.reflect.*;
public class Test05{
    
    public static void main(String[] args) throws Exception{
        
        //获取类
        Class c = Class.forName("java.lang.String");
        
        //获取所有的构造方法
        Constructor[] cs = c.getDeclaredContructors();
        
        for(Contructor con:cs){
            
            //获取修饰符
            System.out.println(Modifier.toString(con.getModifiers()));
            
            //获取名称
            System.out.println(c.getName());
            
            //获取参数列表
            Class[] parameterTypes = con.getParameterTypes();
            for(Class parameterType:parameterTypes){
                System.out.println(parameterType.getSimpleName());
            }
            
        }
        
    }
    
}

获取某个特定的构造方法

/*
	获取某个特定的构造方法
*/
import java.lang.reflect.*;
public class Test06{
    
    public static void main(String[] args) throws Exception{
        
        //获取类
        Class c = Class.forName("Customer");
        
        //获取特定的构造方法
        Constructor con = c.getDeclaredCOnstructor(String.class,String.class);
        
        //创建对象
        Object o = con.newInstance("张三",23);
        
        System.out.println(o);
        
    }
    
}
class Customer{
    String name;
    int age;
    
    Customer(String name,int age){
        this.name = name;
        this.age = age;
    }
    public String toString(){
        return "Customer["+name+","+age+"]";
    }
}

获取一个类的父类和父接口

/*
	获取一个类的父类和父接口
*/
import java.lang.reflect.*;
public class Test07{
    
    //获取String类的父类和父接口
    public static void main(String[] args) throws Exception{
        
        Class c = Class.forName("java.lang.String");
        
        //获取父类
        Class superClass = c.getSuperclass();
        
        //获取父接口
        Class[] ins = c.getInterfaces();
        
    }
    
}

反射机制的两大缺点

1、性能问题:性能比不上直接调用

2、安全问题:打破了封装,使得数据不安全

参考:https://www.bilibili.com/video/BV1kx411h7jv

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Antgeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值