文章目录
一、Java的基本数据类型
Java中提供了8种基本数据类型:
数据类型 | 存储需求 | 默认值 | 取值范围 |
---|---|---|---|
byte | 1 字节,8 位 | 0 | - 128 ~127 |
char | 2字节,16位 | \u0000 | \u0000(十进制等效值为 0) ~ \uffff(即为 65535) |
short | 2 字节,16 位 | 0 | - 327,68 ~ 32,767 |
int | 4 字节,32 位 | 0 | - 2^31 ~ 2^31-1 |
long | 8 字节,64 位 | 0L | - 2^63 ~ 2^63-1 |
float | 4 字节,32 位 | 0.0f | -2^31 ~ 2^31-1(有效位数6~7) |
double | 8 字节,64 位 | 0.0d | -2^63 ~ 2^63-1(有效位数15位) |
boolean | 8 字节,64 位 | false | true 或 false |
注意:char 类型‘0’对应值为48,char 类型‘A’对应值为65,char ‘a’对应值为97 。
二、自动转换与强制转换
2.1自动转换
1.布尔型不参与转换
2.转换规则(总): byte/char/short -> int -> long -> float -> double
3.转换规则(详)
3.1 操作数之一为double,则另一个操作数先被转化为double,再参与算术运算;
3.2 操作数均不为double,当操作数之一为float,则另一操作数先被转换为float,再参与运算;
3.3 操作数均不为double或float,当操作数之一为long,则另一操作数先被转换为long,再参与算术运算;
3.4 操作数均不为double、float或long,则操作数先被转换为int,再参与运算。
特殊:
4.1 如采用+=、*=等缩略形式的运算符,系统会自动强制将运算结果转换为目标变量的类型。
4.2 当运算符为自动递增运算符(++)或自动递减运算符(--)时,如果操作数为byte,short或char类型不发生改变;
5.在做运算时, byte/char/short类型自动转换为int。
2.2强制转换
public class DemoTest {
public static void main(String[] args) {
byte a =1;
int b=2;
a = (byte)b;//强制转换
}
}
三、包装类型
3.1包装类的概念
有时,需要将 int 这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。例如,Integer 类对应基本类型 int。通常,这些类称为包装器(wrapper)。 这些对象包装器类拥有很明显的名字:Integer、Long、Float、Double、Short、Byte、Character、Void 和 Boolean(前6个类派生于公共的超类Number) 对象包装类是不可变的,即一旦构造了包装类,就不允许更改包装在其中的值。同时,对象包装类还是 final,因此不能定义它们的子类。
基本数据类型 | 对应包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
3.2自动拆箱和装箱
自动装箱:能自动的把基本数据类型转换成包装类类型,例如int→Integer。 实际上是调用了方法Integer.valueOf(int)。
自动拆箱: Java自动将包装类型转换为基本数据类型,也就是Integer→int,实际上是调用了方法Integer.intValue()。
什么时候发生自动拆箱:
- 赋值操作:在包装类型和基本数据类型之间进行赋值操作时,会发生自动拆装箱。
- 比较:在包装类型与基本数据类型进行比较时,会先将包装类进行拆箱成基本数据类型(Integer→int),然后再进行比较 。
- 运算符:操作符的只能对基本数据类型进行运算,所以在包装类和基本数据类型进行运算时,会发生自动拆箱,将包装类型转换成基本数据类型进行运算。
注意点:
- 首先,由于包装器类引用可以为 null,所以自动装箱有可能会抛出一个 NullPointerException 异常;
- 另外,如果在一个条件表达式中混合使用 Integer 和 Double 类型,Integer 值就会拆箱,提升为 double,再装箱为 Double;
- 最后,装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用。虚拟机只是执行这些字节码。
四、常量池
Java为大部分基本类型(6种)的包装类(Byte、Short、Integer、Long、Boolean、Character)实现了常量池技术,为它们创建了[-128,127]范围内的缓存数据,具体范围见下表所示。
包装类 | 常量池范围 |
---|---|
Byte | -128 ~ 127(所有) |
Short | -128 ~ 127 |
Integer | -128 ~ 127 |
Long | -128 ~ 127 |
Character | ‘\u0000’ ~ ‘\u007F’ |
Boolean | true和 false |
注意:
- 如果数据大小在缓存数据范围内,那么会直接使用获取常量池中已经创建好的数据;
- 如果不在缓存数据范围内,则会用new Integer(xxx)在堆中创建新的对象。
- Float、Double并没有实现缓存池技术,这是因为浮点型数据有小数,数据个数是不可数的,没办法提前创建。
五、Java变量以及类型
在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下:
type identifier [ = value][, identifier [= value] ...] ;
Java语言支持的变量类型有:
- 类变量:独立于方法之外的变量,用 static 修饰。
- 实例变量:独立于方法之外的变量,不过没有 static 修饰。
- 局部变量:类的方法中的变量。
例如:
public class DemoTest{
static int a=0; // 类变:随着类加载而加载,随着程序结束而销毁
String str="hello world"; // 实例变量:创建对象的时候被加载
public void method(){
int i =0; // 局部变量:必须赋初始值才能使用
}
}
5.2类变量(静态变量)
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
- 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:ClassName.VariableName的方式访问。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
import java.io.*;
public class Employee {
//salary是静态的私有变量
private static double salary;
// DEPARTMENT是一个常量
public static final String DEPARTMENT = "开发人员";
public static void main(String[] args){
salary = 10000;
System.out.println(DEPARTMENT+"平均工资:"+salary);
}
}
5.2实例变量
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
- 当一个对象被实例化之后,每个实例变量的值就跟着确定;
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
- 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
- 实例变量可以声明在使用前或者使用后;
- 访问修饰符可以修饰实例变量;
- 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObjectReference.VariableName。
import java.io.*;
public class Employee{
// 这个实例变量对子类可见
public String name;
// 私有变量,仅在该类可见
private double salary;
//在构造器中对name赋值
public Employee (String empName){
name = empName;
}
//设定salary的值
public void setSalary(double empSal){
salary = empSal;
}
// 打印信息
public void printEmp(){
System.out.println("名字 : " + name );
System.out.println("薪水 : " + salary);
}
public static void main(String[] args){
Employee empOne = new Employee("RUNOOB");
empOne.setSalary(1000.0);
empOne.printEmp();
}
}
5.3局部变量
- 局部变量声明在方法、构造方法或者语句块中;
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
- 访问修饰符不能用于局部变量;
- 局部变量只在声明它的方法、构造方法或者语句块中可见;
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
package com.runoob.test;
public class Test{
public void pupAge(){
int age = 0;//局部变量
age = age + 7;
System.out.println("小狗的年龄是: " + age);
}
public static void main(String[] args){
Test test = new Test();
test.pupAge();
}
}
5.4成员变量和局部变量
(1)在类中的位置不同
-
成员变量:类中方法外;
-
局部变量:方法定义中或者方法声明上;
(2)在内存中的位置不同
-
成员变量:在堆中
-
局部变量:在栈中
(3)生命周期不同
-
成员变量:随着对象的创建而存在,随着对象的消失而消失
-
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
(4)初始化值不同
-
成员变量:有默认值
-
局部变量:没有默认值,必须定义,赋值,然后才能使用