目录
1 冯诺依曼体系
下图是一个典型的冯诺依曼体系:输入设备如键盘、文件等;输出设备如屏幕、文件等;外存储器如硬盘、磁盘、光盘和U盘等;内存储器即电脑的内存(RAM),所有程序都在内存储器中运行;运算器和控制器组在一起称为CPU。
变量: 指的是程序运行时可变的量, 相当于开辟一块内存空间来保存一些数据。
类型: 则是对变量的种类进行了划分, 不同的类型的变量具有不同的特性。
我们所讨论的 “变量” 主要和 “内存” 这样的硬件设备密切相关。
2 注释
注释分为多行注释(块注释)、文档注释和单行注释(行注释)三种。
块注释的快捷键为“ctrl+shift+/”
public class TestDemo {
public static void main(String[] args){
/*
块注释
*/
/**
* 文档注释
*/
/**
*
*/
//行注释
System.out.println("helloworld");
}
3 Java的数据类型
Java的基本数据类型有哪些?
答:Java的数据类型主要分为两大部分,一部分为基本数据类型,另一部分为引用数据类型。
基本数据类型又分为整数类型、浮点类型、字符类型和布尔类型四大类。整数类型里面有:byte、short、int、long;浮点类型里面有:float、double; 字符类型里面有:char;布尔类型里面有:boolean。对于它们的包装类来说,除了int所对应的包装类为Integer;char所对应的包装类为Character;其余都是首字母大写。
引用数据类型分为字符串(String)、数组、类和接口等几大类。
3.1 基本数据类型
3.1.1 整型变量(int)
基本语法格式: int 变量名 = 初始值;
- int 表示变量的类型是一个整型
- 变量名是变量的标识,后续都是通过这个名字来使用变量
- Java 中 = 表示赋值(和数学不一样),意思是给变量设置一个初始值。
- 初始化操作是可选的, 但是建议创建变量的时候都显式初始化。
- 最后不要忘记分号,否则会编译失败。
- // 表示注释,注释作为代码的解释说明部分, 不参与编译运行。
代码示例:
public class TestDemo {
public static void main(String[] args){
int a = 10;//定义一个整型变量
System.out.println(a);
//System.out.println(Integer.MAX_VALUE);
}
}
注意事项:
- int 是4个字节,不区分多少位机器。
- 在Java中int既可以表示正数,也可以表示负数。
- Integer:包装类。把它看为int的plus版本。
- 定义变量且赋值的时候,不能给一个超过其范围的数据,否则会报错,体现了Java的安全性。
- 当变量在定义的时候,没有初始化,那么在使用之前,一定要进行初始化,否则会有编译错误。
什么是字节?
答:字节是计算机中表示空间大小的基本单位,计算机使用二进制表示数据。我们认为 8 个二进制位(bit) 为一个字节(Byte)。平时的计算机为 8GB 内存,意思是 8G 个字节,其中 1KB = 1024 Byte, 1MB = 1024 KB, 1GB = 1024 MB,所以 8GB 相当于 80 多亿个字节。[bit byte kb mb gb tb pb]
4个字节是32位,则最高位为符号位,1表示负数,0表示正数,它表示的数据范围是 -2^31 至 2的31次方减1。如果运算的结果超出了 int 的最大范围, 就会出现溢出的情况。使用以下代码查看 Java 中的整型数据范围:
public class TestDemo {
public static void main(String[] args){
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
运行结果如下图所示:
3.1.2 长整型变量(long)
基本语法格式: long 变量名 = 初始值;
- 基本语法格式和创建 int 变量基本一致, 只是把类型修改成 long。
- 初始化设定的值为 10L , 表示一个长整型的数字,10l 也可以。
- 使用 10 初始化也可以, 10 的类型是 int, 10L 的类型是 long, 使用 10L 或 10l 更好一些。
代码示例:
public class TestDemo {
public static void main(String[] args){
long a = 10L;
System.out.println(a);//定义一个长整型变量
//System.out.println(Long.MAX_VALUE);
//System.out.println(Long.MIN_VALUE);
}
}
注意事项:
1. 长整型long 是8个字节,不区分多少位机器。
2. 数据范围-2^63 至 2的63次方减1。
3. Long:包装类。把它看为long的plus版本。
3.1.3 双精度浮点型变量(double)
基本语法格式: double 变量名 = 初始值;
- double是8个字节,不区分多少位机器。但是浮点数的内存布局和整数差别很大, 不能单纯的用 2 ^ n 的形式表示数据范围。
- Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差。
- Double:包装类。把它看为double的plus版本。
代码示例:
public class TestDemo {
public static void main(String[] args) {
double d = 19.9;
System.out.println(d);
}
}
它所存在的特殊性,例如下述代码:
public class TestDemo {
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println(a/b);
}
}
执行结果为:0。在 Java 中, int 除以 int 的值仍然是 int(会直接舍弃小数部分)。
如果想要得到执行结果为:0.5。需要使用double类型计算。即:
public class TestDemo {
public static void main(String[] args) {
//double d = 19.9;
double a = 1.0;
double b = 2.0;
System.out.println(a/b);
}
}
还需注意下述代码的执行结果并不为1.21,而为:1.2100000000000002,因为Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样), 尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差。
public class TestDemo {
public static void main(String[] args) {
double a = 1.1;
System.out.println(a * a); }
}
// 执行结果
1.2100000000000002
3.1.4 单精度浮点型变量(float)
基本语法格式: float 变量名 = 初始值;
- float是4个字节,不区分多少位机器。
- Float:包装类。把它看为float的plus版本。
代码示例:
public class TestDemo {
public static void main(String[] args) {
float f = 12.5f; // 写作 12.5F 也可以
System.out.println(f);
}
如果少了数字后面的f或者F,则会编译报错,因为12.5就默认为double类型了,所以要是想要使用float类型,则必须在数字后面加f或者F。但表示的数据精度范围较小,所以一般在工程上用到浮点数都优先考虑double,不太推荐使用float。
3.1.5 字符类型变量(char)
基本语法格式: char 变量名 = 初始值;
- char是2个字节,16位,不区分多少位机器。一个汉字两个字节。
- Java 中使用 单引号 + 单个字母 的形式表示字符字面值。
- 计算机中的字符本质上是一个整数,在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符。因此一个字符占用两个字节, 表示的字符种类更多, 包括中文。
- Character:包装类。把它看为char的plus版本。
代码示例:
public class TestDemo {
public static void main(String[] args) {
char c = '高';
System.out.println(c);
char c2 = 19;//unicode
System.out.println(c2);
}
}
代码运行结果如图所示:
使用命令行运行程序,执行 javac 的时候可能出现以下错误:
Test.java:3: 错误: 未结束的字符文字
char ch = '鍛?';
^
因为创建文件是使用UTF8创建的文件,但javac编译的时候,是使用GBK进行编译的,所以我们应该去指定编译的格式,即:Javac -encoding utf-8 TestDemo.java。
3.1.6 字节类型变量(byte)
基本语法格式: byte 变量名 = 初始值;
代码示例:
public class TestDemo {
public static void main(String[] args) {
byte b = 10;
System.out.println(b);
byte c = 2;
// byte d = b+c; error
System.out.println(c);
}
}
注意事项:
- byte是1个字节,8bit,不区分多少位机器。
- Byte:包装类。把它看为byte的plus版本。
- 字节类型表示的也是整数。 它的取值范围为-128至127,即-2^7至2的7次方减1。
- 字节类型和字符类型互不相干。
3.1.7 短整型变量(short)
基本语法格式: short 变量名 = 初始值;
代码示例:
public class TestDemo {
public static void main(String[] args) {
short s = 19;
System.out.println(s);
}
}
注意事项:
- short是2个字节,不区分多少位机器。
- 它的取值范围为-2^15至2的15次方减1。
3.1.8 布尔类型变量(boolean)
基本语法格式: boolean 变量名 = 初始值;
代码示例:
public class TestDemo {
public static void main(String[] args) {
boolean flg = true;
System.out.println(flg);
/* System.out.println(flg + 1);
这句代码编译会出现如下错误:
Test.java:4: 错误: 二元运算符 '+' 的操作数类型错误
System.out.println(value + 1); ^
第一个类型: boolean
第二个类型: int
*/
}
}
注意事项:
- 在JVM标准中,并没有规定布尔类型占几个字节。有人说它是1个字节,也有人说它是1bit,这个没有明确规定。
- 在Java中,boolean 类型的变量只有两种取值, true 表示真, false 表示假。
- Java 的 boolean 类型和 int 不能相互转换, 不存在 1 表示 true, 0 表示 false 这样的用法。
3.2 引用数据类型
3.2.1 字符串类型变量(String)
基本语法格式: String 变量名 = “初始值”;
代码示例:
public class TestDemo {
public static void main(String[] args) {
String str = "hello";
System.out.println(str);
}
}
执行结果为:hello。
注意事项:
- C语言中没有字符串类型,只有一个指针。
- 把一些字符放到一起就构成了字符串。
- Java 使用 双引号 + 若干字符 的方式表示字符串字面值。
- 和上面的类型不同, String 不是基本类型, 而是引用类型。
- 字符串中的一些特定的不太方便直接表示的字符需要进行转义。
转义字符:
例如创建一个字符串,执行结果为:“hello”,这时就需要转义字符的存在了。所需代码为:
public class TestDemo {
public static void main(String[] args) {
String str1 = "\"hello\"";
System.out.println(str1);
}
}
又如创建一个字符串 My name is “张三”,这时也就需要转义字符的存在了。所需代码为:
public class TestDemo {
public static void main(String[] args) {
String str1 = "My name is \"张三\"";
System.out.println(str1);
}
}
常见的转义字符如下表所示:
转义字符 | 解释 |
---|---|
\n | 换行 |
\t | 水平制表符 |
\ ’ | 单引号 |
\ " | 双引号 |
\ \ | 反斜杠 |
字符串拼接:
字符串的 + 操作, 表示字符串的拼接。任何类型的数据和字符串使用+进行拼接其结果就是一个字符串。例如下述代码用字符串和整数进行拼接::
public class TestDemo {
public static void main(String[] args) {
String str1 = "\"hello\"";
int a = 10;
//+ 拼接 任何类型的数据 和 字符串使用+进行拼接,其结果就是一个字符串
System.out.println(a+str1);
}
}
其运行结果为:10"hello"。
又如下述代码:
public class TestDemo {
public static void main(String[] args) {
int a = 10;
System.out.println(110+"hello");
int b = 20;
System.out.println("a = "+a+",b= "+20);
}
}
其运行结果为:110hello 和 a = 10,b= 20。
以上代码说明, 当一个 + 表达式中存在字符串的时候, 都是执行字符串拼接行为。因此,我们可以很方便的使用 System.out.println 同时打印多个字符串或数字。
4 变量
4.1 变量的作用域
变量的作用域也就是该变量能生效的范围, 一般是变量定义所在的代码块 (花括号)。如下述代码所示的变量a,为局部变量,局部变量的作用域在花括号{}内,生命周期为在进入花括号时创建a,在花括号结束时丢掉a。
public class TestDemo {
public static void main(String[] args) {
int a = 10;//局部变量,局部变量的作用域在花括号{}内,生命周期为在进入花括号时创建a,在花括号结束时丢掉a。
{
System.out.println(a);
}
System.out.println(a);
}
}
运行结果为:10和10。
但是如果代码变为下面的样子,则第二个输出在编译时就会失败,显示编译报错。
public class TestDemo {
public static void main(String[] args) {
{
int a = 10;
System.out.println(a);//编译通过
}
System.out.println(a);// 编译失败, 找不到变量a
}
}
4.2 变量的命名规则
标识符包括:数字、字母、下划线 和$。我们给变量命名时需遵循以下建议:
- 不建议使用下划线和$ 开头或者结尾。
- 变量是以小驼峰的形式来定义变量,例如: maxNum(如果是一个单词,首字母小写;如果有多个单词,首字母小写,第二个单词开始大写)
- 不能以数字开头,这是错误的,不合法的。例如: 3age。
- 变量名的大小写是敏感的,即 num 和 Num 是两个不同的变量。
- 虽然语法上也允许使用中文/美元符($)命名变量, 但是强烈不推荐这样做。
- 变量命名要具有描述性, 见名知意。
- 变量名不宜使用拼音(但是不绝对)。
5 常量
常量分为两种,一种为字面常量,一种为final定义的常量。例如:10、10L、true、18.9、18.0F、"hello"这些都是字面常量。关于final定义的常量,它是在程序运行过程当中不可改变的量,它只能初始化一次。例如下述代码:
public class TestDemo {
public static void main(String[] args) {
final int a ;
a = 99;
//a = 88;//如果不屏蔽这句语句,将会编译报错
System.out.println(a);
}
}
或者又如下述代码:
public class TestDemo {
public static void main(String[] args) {
final int a = 10;
//a = 99;//如果不屏蔽这句语句,将会编译报错,提示无法为最终变量a分配值
System.out.println(a);
}
}
6 类型转换
类型转换分为显示类型转换和隐式类型转换。Java是一个强类型编程语言,当不同类型之间的变量相互赋值的时候, 会有教严格的校验。
如int和long、double类型之间的相互赋值,所需用到的类型转换如下:
public class TestDemo {
public static void main(String[] args) {
int a = 10;
long b = 20;
//a = b;编译出错, 提示可能会损失精度
//a = (int)b;强制类型转换
b = a; //编译通过,隐式类型转换
double c = 18.9;
//a = c;编译出错, 提示可能会损失精度
c = a;//编译通过,隐式类型转换
}
}
因为long 表示的范围更大, 可以将 int 赋值给 long, 但是不能将 long 赋值给 int;double 表示的范围更大, 可以将 int 赋值给 double, 但是不能将 double 赋值给 int。
总结: 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型, 反之则不行。
又如int 和 boolean 相互赋值,无论使用什么类型转换方式,均不能实现此赋值。
代码例子如下:
public class TestDemo {
public static void main(String[] args) {
int a = 10;
boolean b = true;
//a = b; 编译出错, 提示不兼容的类型
//b = a; 编译出错, 提示不兼容的类型
}
}
总结: int 和 boolean 是毫不相干的两种类型, 无论采取什么样的方式,均不能相互赋值。
再如将int字面值常量给 byte 赋值,所需用到的类型转换如下:
public class TestDemo {
public static void main(String[] args) {
byte a = 100;
//byte b = 130;//编译报错,因为byte表示的数据范围为-128至正的127,此时数值范围超过了127
int b =130;
a = (byte)b;//编译通过,但强制类型转换是有风险的,即从int转换到byte可能会有损失
}
}
**总结:**使用字面值常量赋值的时候, Java 会自动进行一些检查校验, 判定赋值是否合理,此时所采用的强制类型转换是有风险的,即数据从int转换到byte可能会有损失。因为byte只有一个字节,而int有四个字节。
强制类型转换:
使用强制类型转换的方式可以将 double 类型强制转成 int,但是强制类型转换可能会导致精度丢失。 如下面的例子中, 赋值之后, 10.5 就变成 10 了, 小数点后面的部分被忽略。
并且强制类型转换不是一定能成功, 互不相干的类型之间无法强转,比如int 和 boolean 的相互赋值。例子代码如下所示:
public class TestDemo {
public static void main(String[] args) {
int a = 0;
double b = 10.5;
a = (int)b; //编译通过,但使用强制类型转换可能会导致精度丢失
int a = 10;
boolean b = false;
b = (boolean)a;// 编译出错, 提示不兼容的类型
}
}
类型转换总结:
- 不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型。
- 如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失。并且强制类型转换不是一定能成功, 互不相干的类型之间无法强转。
- 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查。
7 数值提升
当 int 和 long 混合运算的时候, int 会自动提升成 long, 得到的结果仍然是 long 类型, 则需要使用 long 类型的变量来接收结果.。如果我们非要用 int 来接收结果, 就需要使用强制类型转换。我们通过以下代码将对数值提升进行一个具体的理解:
int和long的混合运算
public class TestDemo {
public static void main(String[] args) {
int a = 10;
long b = 19;
// int c = a+b;编译出错, 提示将long 转成 int 会丢失精度
//long d = a + b; // 编译通过.
int c = (int)(a+b);
}
}
byte 和 byte 的运算
public class TestDemo {
public static void main(String[] args) {
byte b1 = 10;
byte b2 = 20;
//byte b3 = b1+b2;CPU取数据时是按照4个字节来取的,当数据类型小于4个字节,如byte只有一个字节,在运算过程中,它会先提升为4个字节进行运算,所以此时会出现编译报错
//int b3 = b1+b2;这样写编译通过,因为int类型就为4个字节
byte b3 = (byte)(b1+b2);//或者使用这样强制类型转换的方式也可以编译通过
//b2 = b2+10;此时会编译报错。因为很明显10就是一个整型,而b2是一个byte类型,在运算过程中,它会先提升为4个字节进行运算,所以此时会出现编译报错
b2 += 10;//+= 复合运算符 它在运算时已经将byte隐式的转为int类型了,就不需要进行强制类型转换了。
}
}
总结:
1.byte 和 byte 都是相同类型, 但是运算时会出现编译报错。原因是:虽然b1和 b2 都是 byte, 但是计算 b1 + b2会先将 b1 和 b2 都提升成 int, 再进行计算, 得到的结果也是 int, 这是赋给 b3, 就会出现上述错误。
2.由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据,为了硬件上实现方便, 诸如 byte 和 short 这种低于
4 个字节的类型, 会先提升成 int, 再参与计算。所以此时如果最终赋值为 byte 和 short 这种低于4 个字节的类型,将会产生编译报错。如果最终赋值必须为 byte 和 short 这种低于4 个字节的类型,则使用强制类型转换的方式也可以编译通过。
数值提升总结:
- 不同类型的数据进行混合运算, 范围小的会自动提升成范围大的。
- 对于 short, byte 这种比 4 个字节小的类型, CPU会先提升成 4 个字节的 int , 再运算。
8 int 和 String 之间的相互转换
int转换成String
将数据从int 转换成 String,我们可以采用直接拼接或者使用String的包装类中所现有的.valueOf(int i)方法进行实现。我们知道,将任何数据与字符串通过+进行拼接就可转换成字符串(String)的形式。代码示例如下:
public class TestDemo {
public static void main(String[] args) {
int a = 10;
//方法1
String string = a + "";
System.out.println(string);
//方法2
String ret = String.valueOf(a);
System.out.println(ret);
}
}
String 转换成 int
将数据从String 转换成 int,我们可以使用int的包装类Integer中所现有的.valueOf(String i)方法进行实现。代码示例如下:
public class TestDemo {
public static void main(String[] args) {
String str = "199";
//包装类的作用,在包装类里面可以有很多的方法来满足你所需实现的功能
int a = Integer.valueOf(str);
System.out.println(a);
int b = a+1;//如果此时b的结果为200,就说明字符串类型的199已经成功转换为了int类型的199
System.out.println(b);
}
}