(1)在java中,有很多class的定义都符合这样的规范:
一、若干private实例字段。
二、通过public方法来读写实例字段。
这种class被称为JavaBean
(1)通过enmu定义的枚举类,和其他的class没有任何区别。enum定义的类型就是class,只不过它有以下几个特点:
一、定义的enum类型总是继承自java.lang.Enum,且无法被继承
二、只能定义出enum的实例,而无法通过new操作符创建eunm的实例(使用private构造方法,确保外部无法调用new操作符)
三、定义的每个实例都是引用类型的唯一实例
四、可以将enum类型用于switch语句
(2)通过name()获取常量定义的字符串,注意不要使用toString();通过ordinal()返回常量定义的顺序(无实质意义);可以为enum编写构造方法、字段和方法;enum的构造方法要声明为private,字段强烈建议声明为final;enum适合用在switch语句中。
(1)使用String、Integer等类型的时候,这些类型都是不变类,一个不变类具有以下特点:
一、定义class时使用final,无法派生子类
二、每个字段都使用final,保证创建实例后无法修改任何字段
(1)在Java中,由CPU原生提供的整数最大范围是64位long型整数。使用long型整数可以直接通过CPU指令进行计算,速度非常快。使用java.math.BigInteger可以用来模拟一个非常大的整数。BigInteger i= new BigInterger(“123456789456123’);和long型整数运算比,BigInteger不会有范围限制,但缺点是速度较慢。也可以吧BigInteger类型转换成long型。
(1)异常是一种class,因此它本身带有类型信息。异常可以在任何地方抛出,但只需要在上层捕获,这样就和方法调用分离了。
从继承关系可以看出:Throwable是异常体系的根,它继承自Object。Throwable有两个体系:Error和Exception,Error表示严重的错误,程序对此一般无能为力,例如:
OutOfMemoryError:内存耗尽
NoClassDefFoundError:无法加载某个Class
StackOverflowError:栈溢出
而Exception则是运行时的错误,它可以被捕获并处理。某些异常是应用程序逻辑处理的一部分,应该捕获并处理。例如:
NumberFormatException:数值类型的格式错误。
FileNotFoundException:未找到文件
SockerExcepition:读取网络失败
还有一些异常是程序逻辑编写不对造成的,应该修复程序本身,例如:
NullPointerException:对某个null的对象调用方法或者字段。
IndexOutOfBountdsException:数组索引越界。
(2)异常可以分为两大类:
1.RuntimeException以及它的子类;
2.非RuntimeException(包括IOException、ReflectiveOperationException等等)
(3)java规定必须捕获的异常,包括Exception及其子类,但不包括RuntimeException及其子类,这种类型的异常称为CheckedException。不需要捕获的异常,包括Error及其子类,RuntimeException及其子类。
(1)可以使用多个catch语句,每个catch分别捕获对应的Exception及其子类。JVM在捕获到异常后,会从上到下匹配catch语句,匹配到某个catch后,执行catch,然后不再继续匹配。 存在多个catch的时候,子类必须写在前面。
(2)finally语句有几个特点:
一、finally语句不是必须的,可写可不写。
二、finally总是最后执行。
如果没有发生异常,就正常执行try{…}语句块,然后执行fianally。如果发生了异常,就中断执行try{…}语句块,然后跳转执行匹配的catch语句块,最后执行finally。
(1)当某个方法抛出了异常,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个try…catch被捕获为止。
(2)在catch中抛出异常,不会影响finally的执行。JVM会先执行finally,然后抛出异常。
(3)fianally抛出异常后,原来在catch中准备抛出的异常就消失了,因为只能抛出一个异常。没有被抛出的异常称为“被屏蔽”的异常。在极少数的情况下,我们需要获取所有的异常,方法是先用prgin变量保存原始异常,然后调用Throwable.addSuppressed(),把原始异常添加进来,最后在finally抛出。
(1)class(包括interface)的本质是数据类型(Type)。无继承关系的数据类型无法赋值,而class是由JVM在执行过程中动态加载的。JVN在第一次读到一种class类型时,将其加载进class内存。每加载一种class,JVM就为其创建一个Class类型的实例,并且关联起来。
(2)以String类为例,当JVM加载String类时,它首先读取String.class文件到内存,然后为String类创建一个Class实例并关联起来。
Class cls = new Class(String);
这个Class实例是JVM内部创建的,如果我们查看JDK源码,可以发现Class类的构造方法是private,只有JVM能创建Class实例,我们自己的Java程序是无法创建Class实例的。所以,JVM持有的每个Class实例都指向一个数据类型。
(3)由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等,因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。这种通过Class实例获取class信息的方法称为反射(Reflection)。
(4)获取一个class的Class实例方法有三种:
方法一:直接通过一个class的静态变量class获取:
Class cls = String.class;
方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()方法获取:
String s = “Hello”
Class cls = s.getClass();
方法三:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取:
Class cls = Class.forName(“java.lang.String”);
(4)因为class实例在JVM中是唯一的,所以,上述方法获取Class实例是同一个实例。可以用==比较两个实例
(5)用instanceos不但匹配制定类型,还匹配指定类型的子类。用class判断可以精确地判断数据类型,但不能作子类型比较。通常情况下,我们应该用instanceof判断数据类型,因为面向抽象编程时,我们不关心具体的子类型。只有在需要判断一个类型是不是某个class的时候,我么使用class判断实例。
(1)JVM在执行Java程序的时候,并不是一次性吧所有用到的class全部加载到内存,而是第一次需要用到class时才加载。
(2)动态加载class的特性对于Java程序非常重要。利用JVM动态加载class的特性,我们才能在运行期间根据条件加载不同的实现类。例如,Commons Logging总是优先使用Log4j。