Class类的常用的方法
反射的操作涉及到了Class类的相关内容,所以我们这边先大致的了解一下Class类的常用的方法
方法名 | 功能说明 |
static ClassforName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用缺省构造函数,返回一个Class对象的一个实例 |
getName() | 返回此Class对象所表示的尸体(类,接口,数组类或void)的名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class[] getinterfaces() | 返回该类的类加载器 |
ClassLoader getClassLoader() | 返回一个包含某些Constructor对象数组 |
Method getMothed(String name, Class… T) | 返回一个Method对象,此对象的形参类型为paramType |
Fied [] getDelaredFields() | 返回Fueld对象数组 |
package com.linke;
public class reflection {
public static void main(String[] args) throws ClassNotFoundException {
Persin persin = new Student();
System.out.println("这个人是"+ persin.name);
//方式一 通过对象获得
Class aClass = persin.getClass();
System.out.println(aClass.hashCode());
//方式二 通过forName方法获得
Class bClass = Class.forName("com.linke.Student");
System.out.println(bClass.hashCode());
//方式三 通过类名.class获得
Class<Student> cClass = Student.class;
System.out.println(cClass.hashCode());
//方式四 基本内置类型的包装类都有一个Type属性
Class dClass = Integer.TYPE;
System.out.println(dClass);
//获取父类类型
Class superClass = aClass.getSuperclass();
System.out.println(superClass.getName());
}
}
class Persin {
public String name;
public Persin() {
}
public Persin(String name) {
this.name = name;
}
@Override
public String toString() {
return "Persin{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Persin{
public Student(){
this.name = "学生";
}
}
class Teacher extends Persin{
public Teacher(){
this.name = "老师";
}
}
那些类型可以有Class对象
- class: 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类,
- 接口: interface
- 数组: []
- 枚举:ennum
- 注解:annotation
- 基本数据类型:primitice type
- void
import java.lang.annotation.ElementType;
/**
* 所有类型的Class
*/
public class AllClassDemo {
public static void main(String[] args) {
//类
Class objectClass = Object.class;
//接口
Class comparable = Comparable.class;
//一维数组
Class stringClass = String[].class;
//二维数组
Class intClass = int[][].class;
//注解
Class overrideClass = Override.class;
//枚举
Class elementTypeClass = ElementType.class;
//基本数据类型
Class integerClass = Integer.class;
//void
Class voidClass = void.class;
//Class
Class classClass = Class.class;
System.out.println(objectClass);
System.out.println(comparable);
System.out.println(stringClass);
System.out.println(intClass);
System.out.println(overrideClass);
System.out.println(elementTypeClass);
System.out.println(integerClass);
System.out.println(voidClass);
System.out.println(classClass);
}
}
类的价值和ClassLoader的理解
加载:将class文件字节码内容加载到内存中,并将这些静态数据转变 成 发去的运行时数据,然后生成一个代表这个类的java.lang.Class对象
链接: 将Java类的二进制代码合并到JVM的运行状态之中的过程
- 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段你呢,这些内存都将在 发去中进行分配
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
初始化:
- 执行类构造器()方法的过程。类构造器()方法是由编译器自动收集类中所以类变量的赋值动作和静态代码中的语句合并产生的(类构造器是构造类信息的,不是构造该类对象的构造器)
- 当初始化一个类的时候,如果发现其他父类还没有进行初始化,则需要先触发其父类的初始化
- 虚拟机保证一个类的()方法在多线程环境中被正确加锁和同步
什么时候会发生类的初始化
类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类
- new 一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有正在声明这个域才会被初始化,如:当通过子类引用父类的静态变量,不会导致子类初始化
- 通过数组定义类引用,不会触发此类的初始化: 比如 Student [] = new Student[1]
- 引用常量不会初始化此类的初始化(常量在链接阶段就存入调用类的常量池中了)