Java反射基础

Introduction

内容源自对慕课网视频Java反射教程的笔记
慕课网教程-反射——Java高级开发必须懂的

Class类的使用
  1. 类是对象,类是java.lang.Class的对象
  2. 如何表示这个对象
public class ClassDemo1 {
    // Foo的实例对象的表示
    Foo foo = new Foo();
    // 万事万物皆对象,那么Foo这个类怎么作为对象表示出来
}

class Foo {}

我们进入Class的源代码,可以看到一个私有的构造函数(这个构造函数可能因为JDK的版本不同而不同)

/*
 * Private constructor. Only the Java Virtual Machine creates Class objects.
 * This constructor is not used and prevents the default constructor being
 * generated.
 */
private Class(ClassLoader loader) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;
}

说得很明确了只有JVM才能访问。

要想把Foo这个类作为对象表示出来有三种方式,内容基本都在注释里面了

package com.nevercome;

/**
 * @author: sun
 * @date: 2019/4/6
 */
public class ClassDemo1 {

    public static void main(String[] args) {
        // Foo的实例对象的表示
//        Foo foo = new Foo("1");
        Foo foo = new Foo();
        // 万事万物皆对象,Foo这个类怎么作为对象表示出来
        // 任何一个类都是Class的实例对象,但是我我们无法用构造函数的方式
        // 但其实有三种方式
        // 1. .class
        Class c1 = Foo.class; // 这说明所有的类,都有一个为class的静态变量
        // 2. 已知该类的对象 getClass()
        Class c2 = foo.getClass();
        // 来梳理一下概念
        // 根据官网的定义: c1,c2 表示了Foo类的类类型(class type)
        // 类类型指的就是类自己,它是Class类的一个实例,如Foo类的类类型就是c1
        // c1是它作为Class类的实例(对象),我们称之为该类(这里是Foo)的类类型


        // c1 和 c2都是Foo的类类型,一个类作为Class类的实例只可能有一个实例对象
        System.out.println(c1 == c2); // true
        Class c3 = null;
        try {
            c3 = Class.forName("com.nevercome.Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println(c2 == c3); // true

        // 我们还可以通过类的类类型来创建该类的对象
        // 这要求该类必须有无参的构造函数(隐式和显示皆可)
        // 不然会抛出NoSuchMethodException
        try {
            Foo foo1 = (Foo)c1.newInstance();
            Foo foo2 = (Foo)c2.newInstance();
            foo.print();
            foo1.print();
            foo2.print();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

}

class Foo {

//    public Foo(String name) {
//
//    }

    public void print() {
        System.out.println("foo");
    }
}
动态加载类 类的反射

上述说的第三种方式Class.forName(“类的权限定名”),不仅代表了类的类类型,还代表了动态加载类。编译时刻加载类是静态加载类,运行时刻加载类是动态加载类。

看一下下面这个Office类:

public class Office {
	public static void mian(String[] args) {
		if("Word".equals(args[0])) {
			Word w = new Word();
			w.start();
		}
		if("Excel".equals(args[0])) {
			Excel e = new Excel();
			e.start();
		}
	}
}

使用javac命令编译这个Office类,毫无疑问,它会报错。因为我们没有Word和Excel类。那么如果你有了Word类呢,当然还是会报错,因为你没有Excel。仔细想一下这个问题,这是否和你的真实需求相背离了呢?我们希望有Word类,Word的功能就可以使用,而不是因为Excel缺失了而所有的Office全家桶都无法使用了。这就是静态加载类(new 都是静态加载),编译时刻要求加载所需的全部类的缺陷。我们希望只有在我们需要使用他们的时候,他们才被加载,Class.forName()可以完成这个任务。

public class OfficeBetter {
	public static void main(String[] args) {
		try {

			// 动态加载类 运行时加载
			Class c = Class.forName(args[0]);
			// 通过类类型创建对象
			// 强制类型转换&#
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值