Java基础杂记(包装类,常量池,枚举,异常)

1 关于JavaBean

JavaBean 是一种符合命名规范的 class,即它通过 private 修饰字段,使用 getter/setter 来定义及获取,此时字段也称为属性,属性是一种通用的叫法,并非Java语法规定。

2 关于包装类

基本数据类型可以转换成对应的包装类,从而获取一些功能上的扩展。除了 IntegerCharacter ,其余的基本数据类型对应的包装类都是其首字母大写的形式表示。
基本数据类型转换为对应的包装类的过程叫做 装箱,包装类转化为基本数据类型的过程叫做 拆箱
装箱的形式有两种:

  • 自动装箱:
int t1 = 10;
Integer t2 = t1;
  • 手动装箱:
Integer t1 = new Integer(10);

拆箱的形式也有两种:

  • 自动拆箱:
Integer t1 = 10;
int t2 = t1;
  • 手动拆箱:
Integer t1 = 10;
int t2 = t1.intValue();

3 关于常量池

《Java内存分配之堆、栈和常量池》

包装类也是引用类型,也是对象,但是在一些情况下的对象之间的比较,却有点特殊,同样的 String 类型也有如此状况。
常量池 指的是在编译期被确定,并被保存在已编译的 .class 文件中的一些数据,除了包含代码中所定义的各种基本类型,还有对象型的常量值final)如:包装类型(FloatDouble 除外),String 类型,还有包含一些以文本形式出现的符号引用,比如:

  • 类和接口的全限定名(全限定名有绝对路径的意思,比如 Java 类包的定名)
  • 字段的名称和描述符
  • 方法和名称和描述符

3.1 关于 String 的内存分配

对于字符串,其对象的引用都是存储在栈中的,而实际内容如果是 编译期 已经创建好(直接用双引号定义的)的就存储在常量池中,如果是 运行期new出来的)就存储在堆中。对于 equals 相等的字符串,常量池中永远只有一份,在堆中可以有多份。

String str1 = "123";
String str2 = "123";
String str3 = new String("123");
System.out.println(str1 == str2);
System.out.println(str1 == str3);
// true false

注意:对于通过 new 产生一个字符串时,会先去常量池中查找是否已经有该对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此对象的拷贝对象。
Strings=new String(“xyz”); 会产生几个对象?答案是:一个或两个,如果常量池中原来没有 xyz,就是两个。

3.2 关于包装类的内存分配

如同 String 类,包装类除了 FloatDouble 外,其它类型都会有使用常量池的情况。
当包装类使用 自动装箱 的形式去实例化对象的时候,它首先会在常量池中查找是否存在这个对象,如果没有就直接在常量池中创建一个,如果有就直接指向该对象。

Integer int1 = 100;
Integer int2 = 100;
Integer int3 = new Integer(100);
System.out.println(int1 == int2);
System.out.println(int1 == int3);
// true false

注意:Integer 类型使用常量池是有限制的,大小必须在 -128127 之间;包装类型与基本数据类型的比较时,包装类型会自动拆箱后再进行比较

4 枚举

枚举Enum可以定义常量类型,它被编译器编译为: final class Xxx extends Enum {...}
可以为枚举类声明构造函数、字段和方法,但值得注意的是枚举类 只能通过自身内部实例化,即无法再外部构造实例,因为 枚举类的构造函数是私有类型,所以其构造函数不能声明为 public
因为枚举实例只有一个,所以可以通过两个枚举实例是否相同可以使用等号判断,使用 name() 方法可以获取枚举实例的常量定义字符串。
eg:

public enum WeekDay {
	// 由于构造函数是private,所以实例化在类的内部创建
	SUN("星期日"), MON("星期一"), TUE("星期二"), WED("星期三"), THU("星期四"), FRI("星期五"), SAT("星期六");
	private String chinese;
	public String toChinese() {
		return chinese;
	}
	WeekDay(String chinese) {
		this.chinese = chinese;
	}
}

5 关于异常

java异常—检查异常(checked exception)和未检查异常(unchecked exception)

根据Java的异常继承树状图,可以发现Java的异常包括分为两个分支,分别是 Error错误 和 Exception异常:

  • Error 错误一般不是编写的问题,而是由于JVM运行你这段代码出现了问题,比如堆溢出,配置文件出错等,这些你是无法人为的在你代码里可以保证的,必须要额外的去操作,重新配置虚拟机,修改配置文件等等
  • Exception 异常是程序本身可以处理的异常,也就是你常见的空指针异常(NullPointerException),数组超出范围异常(IndexOutOfBoundsException)等等。
    • Exception 异常又可分为运行时异常非运行时异常,非运行时异常需要程序员作出相应的处理

同时Java的异常(即 ErrorException)也可以分为 检测异常非检测异常

5.1 检查异常(checked exceptions)

检测异常就是编译器要求你必须处理的异常,比如说当写某段代码时,编译器会警告你,要求你添加 try...catch 或者 throws 处理异常,此时这个异常就是检测异常,即代码还没有执行,编译器就会检测你的代码是否可能会发生错误异常,并要求你对这种可能出现的情况 必须 作出相应的处理,所以对于检查的异常必须处理,或者必须强制捕获或者必须抛出。

除了 RuntimeException 与其子类,以及 Error 错误,其他的都是检查异常

5.2 非检查异常(unchecked exceptions)

编译器不要求强制处置的异常,虽然你有可能出现错误,但是我不会在编译的时候检查,没必要,也不可能。比如 NullPointerException,这些异常通常都需要运行过后才能发生。

非检查异常有:RuntimeException 与其子类,以及 Error 错误

5.3 异常的转换

printStackTrace 可以打印出异常传播的方法调用栈

当捕获一个异常后,可以在捕获之后的 catch 语句中将返回另一个异常,从而达到异常的转换效果,但此时值得注意的是,如果这时候使用了 printStackTrace 打印异常传播的调用栈,会发现并没有原始的异常信息,如果想要跟踪到原始异常的信息,则需要在抛出新的异常时,将保留的原始异常传入到异常中。
eg:

public static void main(String[] args) {
	try {
		Integer.parseInt(null);
	} catch (NumberFormatException e) {
		throw new IllegalArgumentException(e); // 传入原始异常
	} finally {
		System.out.println("finally"); 
	}
}
  • catch 语句抛出异常的时候,finally 语句会比 catch 语句先执行
  • catch 语句和 finally 语句同时都抛出异常的时候,由于异常只能抛出一个,所以只有 finally 语句抛出的异常会被抛出,而 catch 语句中的异常会被屏蔽掉

5.4 自定义异常

当需要抛出异常的时候,应该优先抛出JDK定义的异常,JDK定义的常用异常:

  • RuntimeException
    • NullPointerException:空指针
    • IndexOutOfBoundsException:越界
    • SecurityException
    • IllegalArgumentException:参数错误
      • NumberFormatException
  • IOException
    • UnsupportedCharsetExceptionFileNotFoundExceptionSocketException。。。
  • ParseExceptionGeneralSecurityExceptionSQLExceptionTimeoutException。。。

自定义异常推荐派生自 RuntimeException,自定义异常应该提供多个构造方法,可以使用IDE根据父类快速创建构造方法。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值