目录
class类
class的常用方法
String classAllPath = "com.demo.Car";
//1、获取到Car类对应的Class对象
Class<?> aClass = Class.forName(classAllPath);
//<?>代表不确定的java类型 car 还是Cat 不确定 当然不写也可以
System.out.println(aClass);
//2、输出这个类的aClass对象是哪一个类的Class对象---class com.demo.Car
System.out.println(aClass.getClass());
//输出运行类型---class java.lang.Class
//3、得到包名
System.out.println(aClass.getPackage().getName());
//4、得到全类名
System.out.println(aClass.getName());
//5、通过aClass创建对象实例---这是一个Car对象了
Car car = (Car)aClass.newInstance();
System.out.println(car);
//6、通过反射获取属性 brand
Field brand = aClass.getField("brand");
System.out.println(brand.get(car));
//输出宝马
//7、通过反射给属性赋值
brand.set(car,"奔驰");
System.out.println(brand.get(car));
//输出奔驰
//8、获取所有的字段属性
Field[] fields = aClass.getFields();
for (Field field : fields) {
//输出字段的名称
System.out.println(field.getName());
//brand
//price
//color
}
获取class对象的六种方式
//1、Class.forName -- 知道全路径
String classAllPath = "com.demo.Car"; //通过配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);//class com.demo.Car
//2、通过类名 类名.class
//多用于参数的传递 比如通过反射得到对应构造器对象
Class cls2 = Car.class;
System.out.println(cls2);//class com.demo.Car
//3、对象.getClass
Car car = new Car();
Class<? extends Car> cls3 = car.getClass();
System.out.println(cls3);//class com.demo.Car
//4、通过类加载器【4种】获取到类的Class对象
//(1)先获得类加载器 car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class<?> cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);//class com.demo.Car
//5、基本数据类型(int,char,boolean,float,double,byte,long,short)以下方式得到Class类对象
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
System.out.println(integerClass);//int
//6、基本数据类型对应的包装类 可以通过.TYPE得到Class对象
Class<Integer> cls6 = Integer.TYPE;
System.out.println(cls6); //int
那些类型由class对象
类加载:
基本说明:
反射是java语言实现动态语言的关键,也就是通过反射实现类动态加载
静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性
import java.util.*;
import java.lang.reflect.*;
public class ClassLoad_
{
public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
System.out.println("请输入key");
String key = scanner.next();
switch(key){
case "1":
//Dog dog = new Dog();//静态加载
//dog.cry();
break;
case "2":
Class cls = Class.forName("person");//加载person类--只有会执行的时候才会加载
Object o = cls.newInstance();
Method m = cls.getMethod("hi");
m.invoke(o);
System.out.println("ok");
break;
default:
System.out.println("do nothing...");
}
}
}
类加载时机
1、当创建对象时(new)----静态加载
2、当子类被加载时 父类也加载 ---- 静态加载
3、调用类中的静态成员时 ---- 静态加载
4、通过反射 ---- 动态加载
类加载的流程
加载阶段:在该阶段的主要目的是将字节码从不同的数据源(class文件、jar包或者网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象
连接---验证阶段:
连接---准备阶段
class A {
//准备阶段 是怎么处理的
//1. n1 是实例属性,不是静态变量,因此在准备阶段是不会分配内存
//2. n2 是静态变量,分配内存 n2 默认初始化为0 不是20
//3. n3 是static final 是常量,他和静态变量不一样 因为一旦赋值 就不变 n3 = 30
public int n1 = 10;
public static int n2 = 20;
public static final int n3 = 30;
}
连接---解析阶段
1、虚拟机将常量池内的符号引用 替换为直接引用(内存地址的引用)的过程
初始化阶段:
//有这个机制保证某个类在内存中,只有一份Class对象
synchronized(getClassLoadingLock(name)){
//....
}