JAVA 入门笔记-包装类型
一,包装类型
- 基本类型:
byte,short,int,long,boolean,float,double,char - 引用类型:所有的
class和interfere类型
引用类型可以赋值为 null, 表示空,但是基本类型不能赋值为 null
基本类型转换为引用类型
// Integer 作为 int 的包装类
public Integer {
private int value;
public Integer(int value) {
this.value = value;
}
public int intValue() {
return this.value
}
}
// 定义好了,就可以像下面这样转换
Integer n = null; // 引用类型可以赋值为 null
Integer n2 = new Integer(1); // 实例化时调用构造函数 Integer
int n3 = n2.intValue(); // 取值
在 java 核心库里面,每个基本类型都有对应的包装类型。
public class Main {
public static void main(String[] args) {
Integer n1 = new Integer(1); // 不推荐使用,会有编译警告
Integer n2 = Integer.valueOf(2); // 静态方法 Integer.valueOf(int) 创建
Integer n3 = Integer.valueOf("3"); // 静态方法 Integer.valueOf(String) 创建
}
}
auto boxing
因为int与Integer之间可以互相转换
int i = 100;
Integer n = Integer.valueOf(i);
int m = n.intValue();
所以java编译器会帮助我们自动在 int 和Integer之间转换
Integer n = 100; // 编译器自动调用Integer.valueOf(int)
int x = n; // 编译器自动调用Integer.intValue();
这种行为叫自动装箱(auto boxing)和自动拆箱(auto unboxing),只发生在编译阶段,目的是减少代码量
不变类
所有的包装类都是不变类
// 修饰类当用final去修饰一个类的时候,表示这个类不能被继承。
// 注意:a. 被final修饰的类,final类中的成员变量可以根据自己的实际需要设计为fianl。
// b. final类中的成员方法都会被隐式的指定为final方法
public final class Integer {
private final int value;
}
不能用==来比较Integer大小,因为它是引用类型,必须使用 equals() 比较
?????
对于较小的相同大小
Integer用==比较会返回 true, ==较大的两个相同的Integer返回false,这是因为Integer是不变类,编译器把Integer x = 127;自动变为Integer x = Integer.valueOf(127);,为了节省内存,Integer.valueOf()对于较小的数,始终返回相同的实例,因此,==比较“恰好”为true,但我们绝不能因为Java标准库的Integer内部有缓存优化就用==比较,必须用equals()方法比较两个Integer。==
进制转换
Integer 类提供了大量方法,最常用的静态方法parseInt()可以把字符串解析成一个整数
int x1 = Integer.parseInt("100"); // 100;
int x2 = Integer.parseInt("100", 16) // 256,16进制
需要注意的是:在计算机内存中,只用二进制表示数据,而基于显示数据的存储和显示分离的思想可以想到,System.out.println(n);这样的打印操作只是核心库将数据转换为十进制输出到屏幕上。
二,JavaBean
JavaBean 是一种符合命名规范的class, 通过 setter,getter 来定义和读取属性
import java.beans.*;
public class Main{
public static void main(String[] args) throw Exception{
var p = new Person();
p.setName("wow");
// person.class 是从 object 继承的 getClass() 方法带来的
BeanInfo info = Introspector.getBeanInfo(Person.class);
// Introspector.getBeanInfo() 可以读取属性列表
for(PropertyDescriptor pd : info.getPropertyDescriptors()) {
System.out.println(pd.getName());
System.out.println(" " + pd.getReadMethod());
System.out.println(" " + pd.getWriteMethod());
}
}
}
class Person {
private String name;
private int age;
// setter and getter
public String getName(){
return this.name
}
public void setName(String name) {
this.name = name;
}
}
四,枚举类
java中,可以通过static final 来定义常量
public class WeekDay {
public static final int SUN = 0;
public static final int MON = 0;
// ...
}
关于
java中的静态变量和非静态变量
一种被
static变量修饰的变量,叫类变量或者静态变量;一种是没有static修饰的,叫成员变量通俗的讲,类的
静态变量在内存中只有一个,java 虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享。静态变量可以通过类名进行访问,其生命周期取决于类的生命周期。而
实例变量取决于类的实例,每创建一个实例,java 虚拟机就会为实例变量分配一次内存,实例变量位于堆栈中,其生命周期取决于实例的生命周期。
由上述可知,访问静态变量的方式为:WeekDay.SUM
enum
上述方式使用常量来表示一组枚举值时会存在一个问题:编译器无法检测某个值的合理性。而为了让编译器能自动检测到某个值是否在枚举值的范围内,并且对于不同的枚举类需要用不同的类型标记,我们可以使用enum 来定义枚举类
public class Main {
public static void main(String[] args) {
WeekDay day = WeekDay.SUN;
if(day == WeekDay.SUN || day == WeekDay.SAT) {
System.out.println("放假啦 !")
}
}
}
enum WeekDay {SUN, MON, TUE, WED, THU, FRI, SAT;}
注意:
-
只需要列举常量名,
enum会自动初始化他们的值 -
Enum 定义的常量自带类型信息,编译器能自动检测类型错误
int day = 1; if(day == WeekDay.SUN) { // Compile error: bad operand types for binary operator '==' // ... } -
不同枚举类型之间不能互相赋值
WeekDay x = WeekDay.SUN; // ok!! WeekDay y = Color.RED; // compile error: inconpatible types
enum 的比较
枚举类是引用类型,按照一般理解,引用类型要用 equals() 来比较,而使用 == 判断时,比较的是两个引用类型是否指代同一个对象。但是enum 的比较是个例外。
if(day == W eekDay.SUN) { //...} // ok !
if(day.equals(WeekDay.SUN)) { //...} // still ok, but more code !
enum 类型
enum 本质就是 class, 只是有一些自己的特性
- 定义的
enum类型始终继承自java.ang.Enum, 并且无法被继承; - 只能定义
Enum的实例,而无法通过new创建实例; - 定义的每个实例都是引用类型的唯一实例;
- 可以将
enum类型用于switch语句
public enum Color {
RED, GREEN, BLUE;
}
// 编译器编译出来的大概是这样:
public class Color extends Enum { // 继承自`java.lang.Enum`
public static final Color RED = new Color(); // 静态常量
public static final Color GREEN = new Color();
public static final Color BLUE = new Color();
private Color() { // 构造函数用 private 修饰,确保外部不能用 new 操作符创建实例
// ...
}
}
其实 enum 跟普通 class没有任何区别,只是 java 语法规定必须使用 enum 关键字