Java笔记--09

以下是SUN提供的反射机制中的类
java.lang.Class;
java.lang.reflect.Construct;
java.lang.reflect.Filed;
java.lang.reflect.Modifier;
反射机制的作用:
1.反编译:.class–>.java
2.通过反射机制访问java类的属性,方法,构造方法等
获取Class类型对象的三种方式
第一种方式:

Class c1 = Class.forName("User");

第二种方式:

//java中每个类型都有class属性
Class c2 = User.class;

第三种方式:

//java语言中任何一个java对象都有getClass方法
User u = new User();
Class c3 = u.getClass();
//因为User这个类在JVM中只有一个,所以c1,c2,c3的内存地址是相同的,    指向堆中唯一的一个对象
System.out.println(c1==c2);//true
System.out.println(c2==c3);//true

注意:第一种方式中最好写类全名:带包名;c1,c2,c3代表User类,它们都是引用,指向JVM堆中的User对象
例如:Class c = Class.forName(“java.util.Date”);
第一种方式和第二种方式的区别

//将A.class文件装载到JVM中的过程,会执行A中的静态语句块
    Class.forName("A");
    //不会执行A中的静态语句块
    Class c=A.class;
    获取Class类型的对象之后,可以创建该类的对象
    Class c = Class.forName("User");
    //创建此Class对象所表示的类的一个新实例
    Object o = c.newInstance();//newInstance方法调用的是无参的构造方法
    if(o instanceOf User){
        User u = (User)o;
        System.out.println(u);
    }

关于java中的可变长参数
格式:
类型… 变量
如果某方法中有可变长参数,则在方法调用的时候,传递的实参可以是0-N个
如果有可以精确匹配的方法,则调用该方法,不会再去执行可变长参数的那个方法
可变长参数只能出现一次,且只能出现在所有参数的最后一位
示例如下:

public class Test(){
        //m1方法中有一个int类型可变长参数
        public static void m1(int... a){//m1方法在调用的时候,传递的实参可以是0-n个
            System.out.println("Test");
        }
        public static void m1(int i){
            System.out.println(i);
        }
        //可变长参数可以等同看做数组
        public static void m2(String... args){
            for(int i=0;i<args.length;i++){
                System.out.print(args[i]);
            }
        }
        public static void m2(String... args){
            for(int i=0;i<args.length;i++){
                System.out.print(args[i]);
            }
        }

        public static void main(String [] args){
            m1();         //Test
            m1(1);        //1   结果是1,不在执行可变长参数的m1方法,而是执行可以精确匹配的m1方法
            m1(1,2);      //Test
            m1(1,2,3);    //Test

            m2("音乐","体育","旅行");//音乐体育旅行
        }
    }

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

    //1.创建属性对象
    Properties p = new Properties();//和Map一样,只不过key和value只能存储字符串类型,key不能重复,如果key重复则value值覆盖
    //2.创建输入流
    FileInputStream fis = new FileInputStream("dbinfo.properties");
    //3.将fis流中的所有数据加载到属性对象中
    p.load(fis);
    //4.关闭流
    fis.close();
    //通过key获取value
    String v = p.getPropoerty("username");
    //输出到控制台
    System.out.println(v);

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

    //1.创建属性对象
    Properties p = new Properties();//和Map一样,只不过key和value只能存储字符串类型,key不能重复,如果key重复则value值覆盖
    //2.创建输入流
    FileReader fr = new FileReader("dbinfo.properties");
    //3.将fis流中的所有数据加载到属性对象中
    p.load(fr);
    //4.关闭流
    fr.close();
    //通过key获取value
    String username = p.getPropoerty("username");
    //通过反射机制创建对象
    Class c = Class.forName(username);
    //创建对象
    Object o = c.newInstance();
    System.out.println(o);

java.lang.Class;
类中常用的方法:

    Class forName();
    Field [] getDeclaredFields();
    Field  getDeclaredField(Steing name);
    Method[] getDeclaredMethods();
    Method getDeclaredMethod(String name,Class... parameterType);
    Constructors[] getDeclaredConstructors();
    Constructors getDeclaredConstructor(Class... parameterType);
    String getName();
    String getSimpleName();
    int getModifiers();
    newInstance();
    String toString();
    Class getSuperclass();
    Class[] getInterfaces();

java.lang.reflect.Field;类中的属性
//要想获取类中的属性,首先要获取整个类
Class c = Class.forName(“User”);
//获取属性Field
Field [] fs = c.getFields();//该方法获取的是所有public修饰的属性
//获取所有属性
Field fs = c.getDeclaredFields();

for(Field field:fs){
int i = field.getModifiers();//获取属性的修饰符对应的数字
String strModifier = Modifier.toString(i);//将该数字转换成对应的字符串修饰符
Class type = field.getType();//获取属性的类型对应的类
String strType = type.getSimpleName();//将该类转换成对应的字符串类型
}
下面演示通过反编译获取类和类中的属性

    Class c = Class.forName("User");
    Field fs = c.getDeclaredFields();
    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);

怎样获取类中某个特定的属性并对其进行修改?

    //获取类
    Class c = Class.forName("User");
    //获取id属性
    Field idF = c.getDeclaredField("id");//private修饰的属性获取不到,可以在创建对象之后,打破封装
    Object o = c.newInstance();
    idF.setAccessible(true);//使用反射机制可以打破封装,导致了java对象的属性不安全
    //给o对象的id属性赋值
    idF.set(o,"123");
    System.out.println(idF.get(o));//123

java.lang.reflect.Method;类中的方法

    //获取类
    Class c = Class.forName("User");
    //获取所有的方法
    Method [] ms = c.getDeclaredMethods();
    for(Method m:ms){
        //修饰符
        System.out.println(Modifier.toString(m.getModifiers));
        //方法的返回值类型
        Class returnType = m.getReturnType();
        String strReturnType = returnType.getSimpleName();
        //方法名
        String strMethodName = m.getName();
        //方法的形式参数
        Class [] parameterTypes = m.getParamterTypes();
        for(Class parameterType:parameterTypes){
            String strParameterType = parameterType.getSimpleName();
        }

    }

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

Class c = Class.forName("UserService");
    //获取某个特定的方法:方法名+形参列表
    Method m = c.getDeclaredMethod("login",String.class,String.class);
    //通过反射机制执行login方法
    Object o = c.newInstance();
    //调用o对象的m方法,传递"admin","123"参数,方法的执行结果是retValue
    Object retValue = m.invoke("admin","123");

java.lang.reflect.Construct;类中的构造方法

    //获取类
    Class c = Class.forName("User");
    //获取所有的构造方法
    Construct [] cs = c.getDeclaredConstructors();
    for(Construct c:cs){
        //修饰符
        System.out.println(Modifier.toString(c.getModifiers));
        //构造方法的返回值类型
        Class returnType = c.getReturnType();
        String strReturnType = returnType.getSimpleName();
        //构造方法名
        String strMethodName = c.getName();
        //构造方法的形式参数
        Class [] parameterTypes = c.getParamterTypes();
        for(Class parameterType:parameterTypes){
            String strParameterType = parameterType.getSimpleName();
        }

    }

获取某个特定的构造方法并创建对象

    //获取类
    Class c =Class.forName("User");
    //获取特定的构造方法
    Constructor con = c.getDeclaredConstructor(String.class,int.class);
    //创建对象
    Object o = con.newInstance("张三",21);

关于类获取父类和父接口

//通过反射机制获取String类的父类和父接口
    //获取类
    Class c = Class.forName("java.lang.String");
    //获取父类
    Class superClass = c.getSuperclass();
    System.out.println(superClass.getName());
    //获取父接口
    Class[] ins = c.getInterfaces();
    for(Class in:ins){
        System.out.println(in.getName());
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值