数据类型
Java语言是强类型语言,对于每一种数据都给出了明确的数据类型,不同的数据类型 也分配了不同的内存空间 所以它们表示的数据大小 也是不一样的。
数据类型内存占用和取值范围:
范围的大小顺序:byte < short =char < int <long < float <double
- 在网络传输的过程中,为了节省空间,常用字节来作为数据的传输方式。
- 为了和 int 作区分,long 型变量在声明的时候,末尾要带上大写的“L”。
- 为了和 double 作区分,float 型变量在声明的时候,末尾要带上小写的“f”。不需要使用大写的“F”,是因为小写的“f”很容易辨别。
- double 同样不适合用于精确的数值,比如说货币,最好使用 BigDecimal。
- char 既然只有一个字符,为什么占 2 个字节呢?
- 主要是因为 Java 使用的是 Unicode 字符集而不是 ASCII 字符集。
为什么数组也是引用类型呢?
下面这段代码:
public class ArrayDemo {
public static void main(String[] args) {
int [] arrays = {1,2,3};
System.out.println(arrays);
}
}
arrays 是一个 int 类型的数组打印结果如下所示:
[I@2d209079
[I 表示数组是 int 类型的,@ 后面是十六进制的 hashCode——这样的打印结果太“人性化”了,一般人表示看不懂!为什么会这样显示呢?查看一下 java.lang.Object 类的 toString() 方法就明白了。
数组虽然没有显式定义成一个类,但它的确是一个对象,继承了祖先类 Object 的所有方法。那为什么数组不单独定义一个类来表示呢?就像字符串 String 类那样呢?
一个合理的解释是 Java 将其隐藏了。假如真的存在一个 Array.java,我们也可以假想它真实的样子,它必须要定义一个容器来存放数组的元素,就像 String 类那样。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
为什么接口是引用类型?
对于接口类型的引用变量来说,你没法直接 new 一个:
只能 new 一个实现它的类的对象——那自然接口也是引用数据类型了。
来看一下基本数据类型和引用数据类型之间最大的差别。
-
基本数据类型: 1、变量名指向具体的数值。 2、基本数据类型存储在栈上。 -
引用数据类型: 1、变量名指向的是存储对象的内存地址,在栈上。 2、内存地址指向的对象存储在堆上。
数据类型转换
-
隐式类型转换:
- 规则: 是从小范围的数据类型 直接转到 大范围的数据类型
范围的排序:byte < short = char < int < long < float < double
运用规则:
- 比int大(或者等于)的类型, 在进行运算的时候, 小类型会自动提升为大类型进运算
- :比int小的数据类型, 在进行运算的时候,所有的都要提升为 int类型 再去运算。
-
强制类型转换:
- 规则:是从大范围的数据类型 强制转到 小范围的数据类型
-
强制类型转换的注意事项:
-
boolean类型 不参与任何的类型转换. -
常量优化机制:
1.比int小的类型 才有常量优化机制:byte、short、char int 2.写一个整数常量的时候, 整数常量也是有数据类型的, int类型 3.写一个小数常量的时候,小数常量也是有数据类型的, double类型。
问题疑问:byte d = 3 + 4; 为什么不会出现错误?
public class Test {
public static void main(String[] args) {
byte d = 3 + 4;
}
}
因为3和4,是两个常量,Java中存在【常量优化机制】
常量优化机制:在编译时(javac),就会将3和4计算出一个7的结果,并且会自动判断该结果是否在byte取值范围内。
在:编译通过
不在:编译失败
long类型的数据后面 为什么要加L?
class Demo {
public static void main(String[] args){
int a = 100;
long lo = a; // 正确 隐式类型转换
long lon = 100; // 正确。 既然是正确的 那么为什么老师一直说 让我在long类 型的数据后面 加一个L呢 实在不懂。
System.out.println(100); // 100 是int类型
//System.out.println(10000000000); //100亿 int类型 (int类型的数据 最大到21亿左右)
// 此时 报错了, 100亿已经超过了int数据类型
// 但是 直接写一个 整数常量 确实就是int类型的啊, 所以肯定报错。
// 所以 我们就想 我们能不能写一个整数的时候 让jvm把他当做是一个long类型的数据呢,
而不是int呢, 可以啊 你只需要在数据后面加一个 L就可以了。
System.out.println(10000000000L);
long lo = 100;
}
}
运算符
运算符包括: 算术运算符、赋值运算符、逻辑运算符、比较运算符、三元运算符、位运算符
- 和逻辑运算符基本是一样的, 只不过 逻辑运算符运算的true和false 位运算符运算的是1和0 ,你就可以 把1当做true 把0当做false 然后进行逻辑运算。
- & 有0则0 任何数 和0 去与运算 都是0
- | 有1则1 同种类型里面 一个数 和 同种类型里面的最大数 去或运算 得到 最大数
- ~ 非0则1 ~x = -(x+1)
- ^ 或 不同则true 对应1 相同则false 对应0 两个相同的数 异或 结果是0,规律: 一个数和0去异或 得到自身。 一个数 和另外一个数异或两次 还是自身。
- << 左移 *2^
- 有符号右移 /2^
int a = 60, b = 13;
System.out.println("a 的二进制:" + Integer.toBinaryString(a));
System.out.println("b 的二进制:" + Integer.toBinaryString(b));
int c = a & b;
System.out.println("a & b:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = a | b;
System.out.println("a | b:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = a ^ b;
System.out.println("a ^ b:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = ~a;
System.out.println("~a:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = a << 2;
System.out.println("a << 2:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = a >> 2;
System.out.println("a >> 2:" + c + ",二进制是:" + Integer.toBinaryString(c));
c = a >>> 2;
System.out.println("a >>> 2:" + c + ",二进制是:" + Integer.toBinaryString(c));
|