Thinking in JAVA:类型信息(1)

RTTI:

  • 运行时的对象类型信息识别,大方向可以分为两种
    • 最传统的RTTI就是静态识别,程序编译之后,编译器就知道该对象的类型信息
    • 运行时识别,需要用到反射机制

Class对象

  • 每个类都拥有一个Class对象,这个Class对象会被存储到与类名相同的.class文件里面
  • 这个对象的存在,让反射机制得以实现
  • 为了生成某个类的对象,JVM将使用其中的类加载器
  • 类加载器首先检查对应类的Class对象是否已经加载,如果没有,默认的加载器就会根据类名查找.class文件(字节码)。
  • Class对象被加载到内存的时候,就会被用来创建这个类的所有对象。
class Candy{static print("Loading Candy");}
class Gum{static print("Loading Gum");}
class Cookie{static print("Loading Cookei");}
public class SweetShop{
	public static void main(String[] args){
		print("inside main");
		new Candy();
		print("After creatingcandy");
		try{
			Class.forName("Gum");
		}catch(ClassNotFOundException e){
			print("Couldn't find Gum");
		}
		print("After Class.ForName(\"Gum\")");
		new Cookie();
		print("After creating Cookie"); 
	}
}
  • 上面代码的输出中,会发现每一个类在第一次加载的时候,static成员都会被执行。
  • Class.forName(String s)在找到s对应的类的时候,如果对应类没有被加载,那么就加载它,该函数的返回值是Class对象的引用。此外,这个s必须包含完整的类名(加上包名)
  • 只要想在运行时使用类型信息,就需要先获得对恰当的Class对象的引用,Class.forName是一种获取途径,在感兴趣的类已经创建了一个对象之后,也可以使用obj.getClass()的方式获得对应对象的Class引用。

类字面常量

  • .class被称为类字面常量,这里千万不要和文件的.class弄混了,这个相当于数组的.length这样的成员,表示的是类对象的而引用信息。
  • 使用.class来创建对应类Class对象的引用的时候,并不会自动初始化Class对象。 实际上,类对象的创建分为三个部分
    • 加载:通过类加载器执行。查找字节码(一般是在classpath指定的路径中查找),从字节码中创建一个Class对象
    • 链接:验证类中的字节码,为静态域分配存储空间,解析这个类创建的对其他类的所有引用
    • 初始化(惰性):如果有父类,那么对其进行初始化,执行静态初始化器静态初始化块。这一个步骤不会在链接之后立马执行,而是延迟到对静态方法(static如构造器),或者非final静态域首次引用是才执行。

泛化的class引用

  • Class引用总是指向某个Class对象,可以制造实例,并包含可以作用域这些事例的所有方法的代码。
	public class GenericClassReferences{
		public static void main(){
			Class intClass = int.class;
			Class<Integer> genericIntClas = int.class;
			genericIntClass = Integer.class;
			intClass = double.class; //legal
			//genericIntClass = double.class;//illegal
		}
	}
  • 泛型类引用只能赋值为指向其声明的类型,但是普通的类引用可以被重新赋值为指向任何其他类型的Class对象;换句话说,其实泛型语法会让编译器更进一步检查类引用的类型。
  • 虽然包装类Integer是继承自Number类,但是如果写
Class<Number> genericNumberClass = int.class;
  • 会出现问题,因为Integer.class并非Number.class的子类,这点要且介。
  • 那么如果我们想要和多态一样,通过Number.class来表示各种继承类的Class对象,比如Integer.class, Double.class,要怎么写呢?java提供了?通配符以及extends关键字
    • 其中通配符意味着,Class<?>作用等价于非泛型Class
    • extends意味着,Class<? extends Obj> 表示的类引用是Obj类的子类对象的类信息
	public class BoundedClassReferences{
		public static void main(String[] args){
			Class<? extends NUmber> bounded = int.class;
			bounded = double.class;
			bound = Number.class;
		}
	}
  • Class对象可以通过调用newInstance()方法来产生对象
class CountedInteger{
	private static long counter;
	private final long id = count++;	//?
	public String toString(){return Long.toString(id);}
}

public class FilledList<T>{
	private Class<T> type;
	public FilledList(Class<T> type) {this.type = type;}
	public List<T> create(int nEle){
		List<T>result = new ArrayList<T>();
		try{
			for(int i = 0;i < nEle;i++)	result.add(type.newInstance());
		}catch(Exception e){
			throw new RuntimeException(e);
		}
		return result;
	}
	public static void main(String[] args){
		FilledList<CountedInteger> fl= new FilledList<CountedInteger>(CountedInteger.class);
		System.out.println(fl.create(15));
	}
}
  • 新的转型方法.cast(),对无法使用普通括号转型的情况很有用,调用者为想要编程的Class对象引用,传入参数为想要转型的对象obj,感觉有点类似于String.asValue(int)
	class Building{}
	class House extends Building{}
	public class ClassCasts{
		public static void main(String []args){
			Building b = new House();
			Class<House> houseType = House.class;
			House h = houseType.cast(b);
			h = (House)b;
		}
	}

参考书

  • 《JAVA编程思想》
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博私信或留言,博看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博删除。 6、可私信博看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博私信或留言,博看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博删除。 6、可私信博看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博私信或留言,博看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博删除。 6、可私信博看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值