XFCall java学习笔记(八)

类型信息

class 对象

类是程序的一部分,每个类都有一个 Class 对象。为了生成这个类的对象,Java 虚拟机 (JVM) 先会调用"类加载器"子系统把这个类加载到内存中。类加载器首先会检查这个类的 Class 对象是否已经加载,如果尚未加载,默认的类加载器就会根据类名查找 .class 文件。

  • 所有 Class 对象都属于 Class 类,
Class.forName("Gum");

我们可以使用 forName() 根据目标类的类名(String)得到该类的 Class 对象.如果找不到要加载的类,它就 会抛出异常 ClassNotFoundException。使用该方法你不需要先持有这个类型 的对象。

  • 如果你已经拥有了目标类的对象,那就可以调用 对象名.getClass() 方法来获取 Class 引用。

类字面量

类名.class来获取类对象的使用。效率更高。不仅可以应用于普通类,也可以应用于接口、数组以及基本数据类型。

  • 为了使用类而做的准备工作实际包含三个步骤:
  1. 加载,这是由类加载器执行的。该步骤将查找字节码(通常在classpath 所指定的路径中查找,但这并非是必须的),并从这些字节码中创建一个 Class 对象。
  2. 链接。在链接阶段将验证类中的字节码,为 static 字段分配存储空间,并且如果需要的话,将解析这个类创建的对其他类的所有引用。
  3. 初始化。如果该类具有超类,则先初始化超类,执行 static 初始化器和 static 初始化块。
  • 当使用 .class 来创建对 Class 对象的引用时,不会自动地初始化该 Class 对象。直到第一次引用一个 static 方法(构造器隐式地是 static)或者非常量的 static 字段,才会进行类初始化

  • 如果一个 static final 值是“编译期常量”,那么这个值不需要对 类进行初始化就可以被读取。但是,如果只是将一个字段设置成为 staticfinal,还不足以确保这种行为。

  • 如果一个 static 字段不是 final 的,那么在对它访问时,总是要求在它被读取之前,要先进行链接(为这个字段分配存储空间)和初始化(初始化该存储空间)

import java.util.*;

class Initable {
    static final int STATIC_FINAL = 47;
    static final int STATIC_FINAL2 =
        ClassInitialization.rand.nextInt(1000);
    static {
        System.out.println("Initializing Initable");
    }
}

class Initable2 {
    static int staticNonFinal = 147;
    static {
        System.out.println("Initializing Initable2");
    }
}

class Initable3 {
    static int staticNonFinal = 74;
    static {
        System.out.println("Initializing Initable3");
    }
}

public class ClassInitialization {
    public static Random rand = new Random(47);
    public static void
    main(String[] args) throws Exception {
        Class initable = Initable.class;没有引起初始化
        System.out.println("After creating Initable ref");
        没有引起初始化
        System.out.println(Initable.STATIC_FINAL);
        引起初始化
        System.out.println(Initable.STATIC_FINAL2);
         引起初始化
        System.out.println(Initable2.staticNonFinal);
        Class initable3 = Class.forName("Initable3");
        System.out.println("After creating Initable3 ref");
        System.out.println(Initable3.staticNonFinal);
    }
}

输出结果:

After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74
  • 可以使用泛型对 Class 引用所指向的 Class 对象的类型进行限定。
Class<Number> geenericNumberClass = int.class;

Integer 继承自 Number。但事实却是不行,因为 IntegerClass 对象并不是 NumberClass 对象的子类

  • 将通配符与 extends 关键字配合使用,创建一个范围限定。
public class BoundedClassReferences {
    public static void main(String[] args) {
        Class<? extends Number> bounded = int.class; 
        bounded = double.class;
        bounded = Number.class;
    }
}
  • 使用泛型产生确切类型
Class<? super FancyToy> up = ftClass.getSuperclass();
 Object obj = up.newInstance(); 返回object对象
  • 关键字 instanceof。它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,
if(x instanceof Dog)
    ((Dog)x).bark();向下转型
  • 有一个带一个参数的构造器,编译器不会自动地为我们加上无参构造器。

  • Class 支持反射的概念, java.lang.reflect 库中包含类 FieldMethodConstructor(每一个都实现了 Member 接口)。

动态代理

可以通过调用静态方法 Proxy.newProxyInstance() 来创建动态代理,该方法需要一个类加载器(通常可以从已加载的对象中获取),希望代理实现的接口列表(不是类或抽象类),以及接口 InvocationHandler 的一个实现。

import java.lang.reflect.*;
interface SomeMethods {
    void boring1();

    void boring2();

    void interesting(String arg);

    void boring3();
}

class MethodSelector implements InvocationHandler {
    private Object proxied;

    MethodSelector(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object
    invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if (method.getName().equals("interesting"))
            System.out.println(
                    "Proxy detected the interesting method");
        return method.invoke(proxied, args);
    }
}


class Implementation implements SomeMethods {
    @Override
    public void boring1() {
        System.out.println("boring1");
    }

    @Override
    public void boring2() {
        System.out.println("boring2");
    }

    @Override
    public void interesting(String arg) {
        System.out.println("interesting " + arg);
    }

    @Override
    public void boring3() {
        System.out.println("boring3");
    }
}

class SelectingMethods {
    public static void main(String[] args) {
        SomeMethods proxy =
                (SomeMethods) Proxy.newProxyInstance(
                        SomeMethods.class.getClassLoader(),
                        new Class[]{ SomeMethods.class },
                        new MethodSelector(new Implementation()));
        proxy.boring1();
        proxy.boring2();
        proxy.interesting("bonobo");
        proxy.boring3();
    }
}

输出结果:

boring1
boring2
Proxy detected the interesting method
interesting bonobo
boring3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值