Java 读书笔记 14.1-14.6 RTTI

RTTI

Runtime Type Information
好吧,时隔多日我又来啃这块骨头了;

RTTI顾名思义 运行时类型信息;编译的时候不知道,只有当具体运行时才知道是什么类型信息;Java编程思想好像也没说是怎么具体实现的;我也只能管中窥豹了;

首先,我们知道多态,那么多态是啥呢?
维基百科说:
多态也可定义为“一种将不同的特殊行为和单个泛化记号相关联的能力”

这就让我想起了继承关系;不论是哪个子类都可以用父类表示;编译时是父类,运行时就变成子类了;这就是RTTI了;厉害吧;

Class对象

首先想知道Class对象是什么,必须清楚类,类实例化之后形成一个对象;
这是我们常见的:类和对象?那么类是什么?对于虚拟机来说,他怎么区别这个对象和那个对象不一样呢? 这就靠类对象了;通过类对象,我们就知道“类型”;
举个例子;我们说狮子,一般是一个名词,指代一种生物,某个狮子就是狮子这个类的实例化;但是我们的大脑,社会上的文字,是要储存狮子的定义的;这样你知道Class对象是什么了吧;

class调用顺序

public class Candy {
    public Candy() {
        System.out.println("ccandy");
    }
    {
        System.out.println("no static");
    }
    static
    {
        System.out.println("loading Cnady");
    }

}
public class SweetShop {
    public  static  void  main(String [] arg) throws ClassNotFoundException {
        new Candy();
        Class a =Class.forName("Class.Gum");   //会直接加载类
    }
}
output:
loading Cnady
no static
ccandy
loading Gun

类字面常量

想调用类有三种方式

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种:Class c1 = Code.class;
        Class class1=ReflectDemo.class;
        System.out.println(class1.getName());

        //第二种:Class c2 = code1.getClass();
        ReflectDemo demo2= new ReflectDemo();
        Class c2 = demo2.getClass();
        System.out.println(c2.getName());

        //第三种:Class c3 = Class.forName("com.trigl.reflect.Code");
        Class class3 = Class.forName("com.tengj.reflect.ReflectDemo");
        System.out.println(class3.getName());
    }
}

第一种的Code.class又叫做类字面常量,好处是不会直接初始化class对象,仅仅是加载;
使用类的准备工作有
1. 加载
2. 链接
3. 初始化,由于java很懒,所以都是啥时候用到啥时候加载,所以直接的forName就有点不好玩了;初始化要延迟到静态方法被调用,(所以构造函数也是静态方法),或者非常数讲台域被引用的时候;

泛化的class引用

  1. 简单地说就是class引用带了类型,只接受这种,或者一部分的class对象;
  2. instance与instanceof,简单说一个要比名字,另一个比的是class对象,对象可以动态传参,所以就方便许多;
  3. instance和class比较时的区别 instance会考虑继承;即:麻雀是鸟,但是class不会这么比,麻雀!=鸟;

反射

其实就是通过class对象来获取类中的相关内容比如获取一个方法
以下代码来源:”

public class Person {
    private String name;
    private int age;
    private String msg="hello wrold";
 public String getName() {
        return name;
  }

    public void setName(String name) {
        this.name = name;
  }

    public int getAge() {
        return age;
  }

    public void setAge(int age) {
        this.age = age;
  }

    public Person() {
    }

    private Person(String name) {
        this.name = name;
  System.out.println(name);
  }

    public void fun() {
        System.out.println("fun");
  }

    public void fun(String name,int age) {
        System.out.println("我叫"+name+",今年"+age+"岁");
  }
}

public class ReflectDemo {
    public static void main(String[] args){
        try {
            Class c = Class.forName("com.tengj.reflect.Person");
            Object o = c.newInstance();
            Method method = c.getMethod("fun", String.class, int.class);
            method.invoke(o, "tengj", 10);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

或者获取方法组

public class ReflectDemo {
    public static void main(String[] args){
        try {
            Class c = Class.forName("com.tengj.reflect.Person");
            Method[] methods = c.getDeclaredMethods();
            for(Method m:methods){
                String  methodName= m.getName();
                System.out.println(methodName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class ReflectDemo {
    public static void main(String[] args){
        try {
            Class c = Class.forName("com.tengj.reflect.Person");
            //获取成员变量
            Field field = c.getDeclaredField("msg"); //因为msg变量是private的,所以不能用getField方法
            Object o = c.newInstance();
            field.setAccessible(true);//设置是否允许访问,因为该变量是private的,所以要手动设置允许访问,如果msg是public的就不需要这行了。
            Object msg = field.get(o);
            System.out.println(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class ReflectDemo {
    public static void main(String[] args){
        try {
            Class c = Class.forName("com.tengj.reflect.Person");
            //获取构造函数
            Constructor constructor = c.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);//设置是否允许访问,因为该构造器是private的,所以要手动设置允许访问,如果构造器是public的就不需要这行了。
            constructor.newInstance("tengj");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ps:无关思想的细节就不要深究了;

接口与类型信息

1.通过使用反射,即使实现包的访问权限,仍旧可以到达并调用所有方法,甚至是private方法。如果知道方法名,就可以在其Method对象上调用setAccessible(true),然后通过invoke()方法来使用该方法。
2.final域实际上在遭遇修改时是安全的。运行时系统会在不抛异常的情况下接受任何修改尝试,但实际上不会发生任何修改

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值