一,包装类型
- 基本类型:
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
关键字
网友评论