您的位置:首页 > 编程语言 > Java开发

Thinking in java: 14类型信息

2018-03-30 15:16 246 查看
1.  java识别对象和类的信息的两种方式:
   (1)RTTI,她假定我们在编译时已经知道了所有类型;名字含义:在运行时,识别一个对象的类型。
   (2)反射机制,他允许我们运行时发现和使用类的信息。
2. 类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象(更恰当的说是被保存在一个同名的.class文件中)。为了生成这个类的对象,java虚拟机将运行“类加载器”的子系统。
类加载器首先检查这个类的Class对象是否已经加载。如果尚未加载,类加载器就会根据类名查找.class文件。在这个类的字节码被加载时,他们会接收验证,以确保其没有被破坏,且不包含不良代码。一旦某个类的Class对象被载入内存,他就被用来创建这个类的所有对象。
所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这证明构造器也是类的静态方法,即使没有static关键字。因此,java程序在它开始运行之前并非完全加载,其各个部分是在必需时才加载的。class Candy{
static {
System.out.println("Loading Candy");}
}
class Gum{
static {
System.out.println("Loading Gum");
}
}
class Cookie{
static {
System.out.println("Loading Cookie");
}
}

public class Niuke {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After creating Candy");
try {
Class.forName("Gum");
} catch (ClassNotFoundException e) {
System.out.println("Couldn't find Gum");
}
System.out.println("After Class.forName(\"Gum\")");
new Cookie();
System.out.println("After creating Cookie");
}
}
/*
inside main
Loading Candy
After creating Candy
Loading Gum
After Class.forName("Gum")
Loading Cookie
After creating Cookie
*/3.只要你想在运行时使用类型信息,就必须首先获得对恰当的Class对象的引用。有两种方式获得对对象的引用:
     方式一:  使用Class  a = Class.forName("全限定名(包含包名的)"),返回一个Class对象的引用
     方式二:使用类字面常量。例如:类名.class    (FancyToy.class),更简单更安全
  两者区别:.class对类的引用不会引发类的初始化,但是Class.forName()会立即对类进行初始化.需要注意的是:这里是类的初始化(static{}函数),不是类的构造函数。static{}是伴随类加载执行的,且只会执行一次。
另外:如果类的域里面含有编译期常量(static final值),那么这个值不需要对类进行初始化就可以被读取。如果一个static域不是final的,那么在对它访问时,总是要求先进行链接(为域分配存储空间)和初始化(初始化该存储空间)import java.util.Random;

class Initable{
static final int staticFinal = 47;
static final int staticFinal2 = Niuke.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 Niuke {
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.staticFinal); //编译期常量,调用它不用首先对Initable进行初始化
System.out.println(Initable.staticFinal2); //非编译期常量,调用时需要首先强制对Initable初始化
System.out.println(Initable2.staticNonFinal); //非final的,需首先进行链接和初始化

Class initable3 = Class.forName("Initable3");
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}     为了使用类而做的准备工作包含:
       1. 加载。这是由类加载器执行的。该步骤将查找字节码,并从这些字节码中创建一个Class对象。
       2.链接。验证类中的字节码,并未静态域分配存储空间
 
99e3
     3.初始化。如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块
4. instanceof与==来判断类型,instanceof保持了类型的概念,它指的是“你是这个类吗,或者你是这个类的派生类吗?”而如果用==比较实际的Class对象,就没有考虑继承,换句话说,它是这个类型或者不是。
5.反射:运行时的类信息

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: