常用数据类型
常用 8 种基本数据类型如下:
数据类型 | 大小 | 默认值 | 表示范围 | 备注 |
---|---|---|---|---|
byte | 8 位 | 0 | -2^7 到 2^7 - 1 (即 -128 到 127 ) | |
short | 16 位 | 0 | -2^15 到 2^15 - 1 (即 -32,768 到 32,767 ) | |
int | 32 位 | 0 | -2^31 到 2^31 - 1 (即 -2,147,483,648 到 2,147,483,647 ) | |
long | 64 位 | 0L | -2^63 到 2^63 - 1 (即 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 ) | 字面值超过int范围,必须加l或L,例如long l = 11111111111L; ,否则编译错误 |
float | 32 位 | 0.0f | 大约 -3.40282347E+38 到 3.40282347E+38 (使用 IEEE 754 标准) | 字面值必须跟f或F,例如1.2F,否则编译错误 |
double | 64 位 | 0.0 | 大约 -1.7976931348623157E+308 到 1.7976931348623157E+308 (使用 IEEE 754 标准) | |
char | 16 位 | '\u0000' (空字符) | 0 到 2^16 - 1 (即 0 到 65,535 ) | |
boolean | 1 位 | false | true 或者false |
位运算
Java 的位运算是对整数类型的二进制位进行操作的运算,操作数只能是 int 和 long 类型,以及通过类型提升支持的 byte、short 和 char 类型。使用位运算时,通常需要注意类型的提升和转换,以确保运算的正确性。
按位与(&):对应位都为 1 时结果为 1,否则为 0。
示例:5 & 3(0101 & 0011)结果为 1(0001)
按位或(|):对应位至少有一个为 1 时结果为 1,否则为 0。
示例:5 | 3(0101 | 0011)结果为 7(0111)
按位异或(^):对应位相同则为 0,不同则为 1
示例:5 ^ 3(0101 ^ 0011)结果为 6(0110)
按位取反(~):对每一位进行取反,0 变 1,1 变 0
示例:~5(0101)结果为 -6(补码表示)
左移(<<):将位向左移动指定的位数,右侧补零
示例:5 << 1(0101 左移 1 位)结果为 10(1010)
右移(>>):将位向右移动指定的位数,符号位填充
示例:-8 >> 1(11111000 右移 1 位)结果为 -4(11111100)
无符号右移(>>>):将位向右移动指定的位数,左侧补零,不管符号位
示例:-8 >>> 1 结果为 2147483644
二进制相关
显示一个数的二进制
Integer.toBinaryString()
方法来打印 int 类型数字的二进制表示。对于其他类型的数字,如 byte、short 和 long,可以先转换为 int 或 long,然后打印其二进制表示。
public class BinaryRepresentation {
public static void main(String[] args) {
int num = 42; // 示例数字
// 打印 int 类型的二进制表示
String binaryString = Integer.toBinaryString(num);
System.out.println("Integer " + num + " in binary: " + binaryString);
// 打印 byte 类型的二进制表示
byte b = 5;
String byteBinary = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
System.out.println("Byte " + b + " in binary: " + byteBinary);
// 打印 short 类型的二进制表示
short s = 100;
String shortBinary = String.format("%16s", Integer.toBinaryString(s & 0xFFFF)).replace(' ', '0');
System.out.println("Short " + s + " in binary: " + shortBinary);
// 打印 long 类型的二进制表示
long l = 123456789L;
String longBinary = Long.toBinaryString(l);
System.out.println("Long " + l + " in binary: " + longBinary);
}
}
解释如下:
Integer.toBinaryString(int i)
:将 int 类型的数字转换为其二进制字符串表示。String.format()
:用于格式化字符串,确保输出的二进制字符串具有固定的位数。使用%8s
确保byte输出为 8 位,使用%16s
确保short输出为 16 位。b & 0xFF 和 s & 0xFFFF
:将 byte 和 short 转换为 int 类型,确保正确输出其无符号的二进制表示。
固定长度显示
Integer.toBinaryString(int i)
的输出不带符号位,且长度不固定,不会显示一个数字的所有长度的二进制位
/**
* 将整形以二进制形式转换为字符串,长度为32位
*
* @param num 数字
* @return 字符串
* @see Integer#toBinaryString(int)
*/
public static String toBinaryString(int num) {
StringBuilder sb = new StringBuilder();
for (int i = 31; i >= 0; i--) {
sb.append((num & (1 << i)) == 0 ? "0" : "1");
}
return sb.toString();
}
面向对象
类成员
java类的成员有四个
- 属性
- 方法
- 构造器
- 代码块,如果有修饰符则只能用static
属性的赋值顺序
属性的赋值顺序:
1.默认的初始化
2.显示的初始化或非静态初始化代码块(此处两结构按顺序执行)
3.构造器
4.通过对象的方法来对相应的属性进行修改
初始化代码块
非静态初始化代码块
可以有输出语句
可以类的属性、类的声明进行初始化操作
可以调用静态的方法或者变量
若有多个非静态代码块,执行顺序为从上到下的顺序依次执行
每次创建对象的时候,都会执行依次
先于构造器执行
static代码块的使用
可以有输出语句
可以对类的属性、类的声明进行初始化操作
不可以对非静态属性进行初始化。即:不可以调用非静态的属性和方法
若有多个静态代码块,那么执行顺序为从上到下的顺序依次执行
静态代码块的执行要先于非静态代码块
静态代码块只执行一次
public class P {
static {
System.out.println("class p init1");
}
{
System.out.println("object p init");
}
static {
System.out.println("class p init2");
}
public P() {
System.out.println("constructor in P class");
}
}
class C extends P {
static {
System.out.println("class C init1");
}
{
System.out.println("object C init");
}
static {
System.out.println("class C init2");
}
public C() {
System.out.println("constructor in C class");
}
}
class TestClass {
public static void main(String[] args) {
C c = new C();
}
}
执行顺序如下:
class p init1
class p init2
class C init1
class C init2
object p init
constructor in P class
object C init
constructor in C class
集合操作
list集合转数组
调用Collection#toArray方法,以jdk8中的ArrayList为例
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
传参一般有2种方式,使用预大小的数组如c.toArray(new String[c.size()]
或使用空数组如c.toArray(newString[0])
在较旧的Java版本中,建议使用预设大小的数组,因为创建适当大小的数组所需的反射调用非常慢。然而由于后期更新,这个调用变得更加复杂,与预先确定大小的版本相比,空数组版本的性能相同,有时甚至更好。此外,传递预先确定大小的数组对于并发或同步的集合来说是危险的,因为如果集合在操作过程中同时收缩,size和toArray调用之间可能会发生数据竞争,这可能会导致数组末尾出现额外的空值。
这种检查允许遵循统一的风格:使用空数组(这在现代Java中是推荐的)或使用预大小的数组(在旧Java版本或非基于HotSpot的JVM中可能更快)。