目录
前言:之前跟着狂神学了Java的一些基本内容,17个小时的课程断断续续看了两周,学完之后就很长时间没碰Java,基本上忘光了,现在重新跟着尚硅谷来学, 有C语言基础的小伙伴欢迎来一起!
学习Java前的准备
这里我就不再说一遍了,请同学们看我的这篇博客:Java学习前的准备
补充:idea中是有中文插件的,需要的自行百度
public class helloworld{
public static void main(String[] args){
System.out.println("hello world");
}
}
在这里我们再解析一遍这个程序:
- public是修饰class的一个修饰符,具体的作用以后讲
- class后面跟的就是类名
- public修饰的类名必须与文件名相同
- main()就是一个方法,相当于c语言中的main函数,它是程序的入口,前面的void是指它没有返回值,public和static都是修饰它的,具体作用以后讲,而括号里的内容就是参数,它的作用我们也放在后面
- 最后一句话中就相当于c语言中的printf(“hello world\n”);
- 如果是System.out.print(“hello world”);就相当于c语言中的printf(“hello world”);
- Java的风格是尾行风格,所以我们看到的左括号跟在一行的末尾
- Java中print和println方法中打印变量时直接用变量名就可以:
准备好这些,我们就开始学习吧
Java和C
我们知道,我们新建一个C语言文件是以.c或.cpp为后缀的,而Java文件以.java为后缀,一个.java文件中可以定义多个类,但只能定义一个public修饰的类,每一个类中都能定义一个main方法(方法类似于C中的函数),对.java文件编译后,每个类都会生成一个.class文件,我们可以运行有main方法的.class文件(这些只当作一个可选的学习点,后面会具体学习)
Java和C中的运算都是通过补码进行的
变量与运算符
关键字和保留字
关键字
与c语言一样,java中的关键字也不能被用作变量名,常见的java关键字如下:
abstract、assert、boolean、break、byte、case、catch、char、class、const、continue、default、do、double、else、enum、extends、final、finally、float、for、goto、if、implements、import、instanceof、int、interface、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while
是不是看得头疼,没关系,这种关键字我们以后一个一个学,还有很多和C语言中的差不多,并不是很难学。
另外true、false、null这三个用来给部分数据类型赋值的字符串也不能被用作变量名
保留字
Java 保留字:现有 Java 版本尚未使用,但以后版本可能会作为关键字使
用。自己命名标识符时要避免使用这些保留字:如goto、continue
标识符
定义
标识符:Java对各种变量、方法和类等要素命名时使用的字符序列称为标识符。
其实就是:凡是自己可以起名字的地方都叫标识符 。
比如:类名、变量名、方法名、接口名、包名…
标识符命名规则
- 由 26 个英文字母大小写, 0 9 或 $ 组成
- 数字不可以开头。
- 不可以使用关键字和保留字,但能包含关键字和保留字。
- Java 中严格区分大小写,长度无限制。
- 标识符不能包含空格。
例如:miles , Test,a,$4都是正确的,而4#R, #44, class, public, int都是不正确的
标识符命名错误将不能通过编译!
Java中的命名规范
Java 中的名称命名规范:
- 包名 :多单词组成时所有字母都小写 xxxyyyzzz
- 类名、接口名 :多单词组成时,所有单词的首字母大写 XxxYyyZzz
- 变量名、方法名 :多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写: xxxYyyZzz
- 常量名 :所有字母都大写。多单词时每个单词用下划线连XXX_YYY_ZZZ
可能你还不明白这些东西都是什么,没关系,后面我们还会重复讲
注意 1 :在起名字时,为了提高阅读性,要尽量有意义,“见名知意”。
注意 2: java 采用 unicode 字符集,因此标识符也可以使用汉字声明,但是不建议使用。
变量
变量的概念
- 内存中的一个存储区域
- 该区域的数据可以在同一类型范围内不断变化
- 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值
变量的作用
用于在内存中保存数据
使用变量注意
- Java中每个变量必须先声明,后使用
- 使用变量名来访问这块区域的数据
- 变量的作用域:其定义所在的一对大括号内
- 变量只有在其作用域内才有效
- 同一个作用域内,不能定义重名的变量
Java中变量的声明,赋值语法与C语言一样
变量的分类
这些数据如果我们只创建而不初始化,我们将无法使用(报错),不使用的话可以通过。
基本数据类型
- 数值型:
1. 整数类型:byte,short,int,long
2. 浮点类型:float,double - 字符型:char
- 布尔型:boolean
引用数据类型
- 类:class
- 接口:interface
- 数组:array
字符串属于类
成员变量:在方法体外,类内部声明的变量
包括:实例变量,类变量(static修饰的)
局部变量:在方法体内部声明的变量称为局部变量
包括:形参(方法、构造器中定义的变量),方法局部变量(在方法内定义),代码块局部变量(在代码块内定义)
二者的异同
同:二者都具有生命周期
异:局部变量除形参外,都需要初始化
上面都看不懂?没关系哈哈,讲解在后面,前面只是让你们知道有这个东西。
基本数据类型详解
在Java中可以在数字中间加上下划线,方便看出数字的位数,而不会有其它影响:
整数类型讲解
- 与C语言不同,Java中的整数类型都有固定大小:
byte:1字节 范围:-128~127
128超出范围,报错
short:2字节 范围:-215~215-1
int:4字节 范围:-231~231-1
long:8字节 范围:-263~263-1
一个问题:-128的补码是?
如图,255的补码是11111111,因此最后的二进制结果就是a的补码(对每一位,a为1则为1,a为0则为0),即1000000,因此我们知道-128的补码为10000000,我们可以倒退出来它的原码是00000000,我们也可以这样想:-127的补码是10000001,那么它再减去1就是-128,也就是10000000
2. Java 的整型默认为 int 型,声明 long 型常量须后加‘ l’ 或‘ L’,建议写成’L’,不容易与1搞混
定义long型变量时不在数字后加’L’,整数默认为int型,超出范围,报错
加上’L’,默认创建8个字节
3. java 程序中变量通常声明为int型,除非不足以表示较大的数,才使用long
浮点类型详解
- 浮点类型也有固定的大小:
- float(4个字节): 单精度,尾数可以精确到 7 位有效数字。很多情况下,精度很难满足需求。表数范围:-3.403E38 ~ 3.403E38
- double(8个字节):双精度,精度是 float 的两倍。**通常采用此类型。**表数范围:-1.798E308 ~ 1.798E308
- 浮点型常量有两种表示形式:
- 十进制数形式:如: 5.12 、512.0f 、.512 ( 必须有小数点,整数部分不写默认为0)
- 科学计数法形式 如: 5.12e2 、512E2、 100E-2
你会发现,float类型的变量值甚至比int型还要大其实这是因为浮点型储存的方式是一位表示符号位,几位表示指数,剩下的表示指数前面的数
注意:Java 的浮点型常量默认为 double 型 声明 float 型常量,须后加‘ f’ 或‘ F’ 。
如图:不加’F’默认为double型,赋给float型报错
字符类型详解
-
与C语言不同,Java中字符采用Unicode编码,一个字符占用两字节,而这一个字符可以储存字母、汉字、平假名、片假名等
-
Java中也有转义字符,与C语言大致相同
-
字符类型不能为空(但字符串类型可以)
-
Java中字符表示语法与C相同,但Java中还可以用Unicode值表示:’\uXXXX’,其中每个X对应一个十六进制位。这类似于用ASCII码值表示字符。
-
char类型是可以参与运算的,因为每个字符都有对应的Unicode码值
-
对char型变量赋值时也可以直接用Unicode码值
例如:char a=97;a即为’a’
布尔类型详解
- 我们知道,C语言中通常用非0表示真,0表示假,而在Java中不能这样,Java中boolean可以且只能取true或者false来表示真假,不过Java中的布尔值在编译后也是被表示为1(真)或0(假)
- Java中没有给出boolean类型的大小,因为对虚拟机来说根本就不存在 boolean 这个类型,boolean类型在编译后会使用其他数据类型来表示
- 在for、while、do-while循环和if条件判断中,判断语句执行后会返回一个boolean值。
- 使用示例:
基本数据类型转换
自动类型转换
-
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
图中b1与i1运算,b1被提升为int型与i1相加,得到int型结果,,无法赋给byte型变量
-
自动类型转换 :容量小的类型自动转换为容量大的数据类型。
把int型结果赋给int型变量和long型变量都可以,说明发生了自动类型转换
-
数据类型按容量大小排序为:char、short、byte<int<long<float<double,你可能也看出来了:除了char,short,byte三个特殊的,这是按它们取值范围大小排的
b1与i1相加后变为int型,赋给f后自动提升为float型,Java中打印无小数位的浮点数默认打印到小数点后一位
这里short型赋给double型变量自动提升为double型
-
特别注意:byte,short,char 之间不会相互转换,他们三者在计算时首先转换为int类型,即使两个byte类型变量相加仍然会转换为int型
c1与i3相加得到int型结果赋给i4,这样是正确的
这里印证了上述的规则:byte、char、short两两相加都得到int型(即使相同类型两个变量相加也是这样)
-
boolean 类型不能与其它数据类型运算。
-
boolean 类型不可以转换为其它的数据类型 。
-
注意:当把任何基本数据类型的值和字符串(String,S大写)进行连接运算时(即+运算),基本数据类型的值将自动转化为字符串类型 。
使用示例:
强制类型转换
强制类型转换:自动类型提升运算的逆运算。
- 需要使用强转符:()与C语言相同
- boolean 类型不可以转换为其它的数据类型 。
- 注意点:强制类型转换,可能导致精度损失。
几个案例:
如图所示,**d1转换为int型丢失了小数所有部分,这正是浮点型转换为整型的规律!**而long型的123转换为short型仍未丢失精度,因为short型完全可以储存123。128表示为二进制:00000000000000000000000010000000,b只接受补码10000000,即为-128
如图,123213默认为int型且未超过int的范围,因此自动转换为long型,不会报错
而下图这几句报错的原因分别是:
数字超过了int的范围
double不能赋给float(12.3默认为double型)
b+1得到int型不能赋给byte型
double型不能赋给float型(12.3默认为double型)
而如下图就是正确的:- 将数字改为long型
- 将double型强转为float型
字符串类型详解
- 与C语言中必须用数组来表示字符串类型不同,Java中直接有字符串类型
- String 不是基本数据类型,属于引用数据类型
- 使用方式与基本数据类型一致。例如 String str = “abcd”;
- 字符串可以为空,字符不行
- 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据(用+连接,将其它类型转为字符串)。例如:
"sum=“是字符串内的内容,它与sum相加,相当于变为字符串"sum=30”,即变量会被替换为它的值
- String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+,运算结果仍未String型
示例:
下图中从上到下的原因依次为:- c与num运算提升为int型,相加得到107,再与"hello"字符串连接
- c与str连接得到字符串型,再与num连接
- num与str连接得到字符串类型,再与c连接
- 与第一个完全一样
- str与num连接得到字符串类型,再与c连接
- 通常字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现:
其它数据类型同理
这些方法我们在后面会细讲,现在简单了解一下就可以了
变量之进制
-
Java中的数据在计算机中也是以补码形式储存的(请复习原码、反码、补码)
-
Java中整数也可以通过二进制来赋值,以 0b 或 0B 开头。
-
八进制,十六进制与C语言相同。
-
Java中没有无符号数。
-
Java中有转换进制的方法
示例:
我们看到,结果的返回值为String型
同理,我们还可以使用以下方法:
1. 十进制转换为八进制:Integer.toOctalString(int i);
2. 十进制转换为二进制:Integer.toBinaryString(int i);
3. 其他进制转换成十进制:Integer.parseInt(String s, int radix);这个方法比前面的更强大,s对应的是你需要转换的字符串,radix是这个字符串的进制数,示例:
运算符
算术运算符
+、-、*、/、%、++、–等用法与C语言中大致相同
特殊:+可以连接字符串
介绍几个易错点:
- -12%5=-2;5%-2=1;
- Java中不能用++++,带括号也不行
- Java中自增不会改变变量类型
short=short+1中,1是int型,因此要用int型接收
赋值运算符
=、+=、-=、/=、*=、%=等用法与C语言中大致相同
- +=,-=,/=,*=,%=都不会改变数据类型
- Java中可以连续赋值
比较运算符(关系运算符)
==,!=,<,>,>=,<=等用法与C语言中大致相同,instanceof
- 比较运算符的结果要么是true,要么是false,即布尔类型
- instanceof我们会在讲到多态的时候再讲
逻辑运算符
&,&&,|,||,!,^等用法与C语言中大致相同
- 逻辑运算符操作的都是boolean类型的变量
- &和&&、|和||有不同,具体可以看我的另一篇文章:有关逻辑运算符运算规律的验证
- 开发中推荐使用&&和||,效率更高
位运算符
<<、>>、&、|、~、^与C语言中用法大致相同,>>>
- >>>代表无符号右移,因为Java中没有无符号数据类型,因此右移时负数前面默认补1,若是用无符号右移,无论正负左边一律补0
- 位运算的运算效率很高,比如计算2*8,效率最高的是8<<1
- 位运算是补码的运算
补充:交换两个变量值的三种方法
int num1=10,num2=20,tmp;
方式一:定义临时变量的方式
推荐的方式
tmp = num1;
num1 = num2;
num2 = tmp;
方式二:好处:不用定义临时变量
弊端:相加操作可能超出存储范围
有局限性:只能适用于数值类型
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2;
方式三:使用位运算符
有局限性:只能适用于数值类型
num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num1 ^ num2;
三目运算符
(条件表达式)?表达式1:表达式 2;与C语言中用法大致相同
- 表达式1和表达式2为同种类型
- 条件表达式的结果为boolean类型
- 如果程序既可以使用三元运算符,又可以使用if-else结构,那么优先选择三元运算符。原因:简洁、执行效率高。
- 三元运算符可以嵌套使用(不建议,可读性差)
运算符的优先级
不用太过关注,使用时可以用()
- L——>R表示从左向右运算
- R——>L表示从右向左运算
Scanner的使用
如何从键盘获取不同类型的变量:需要使用Scanner类,具体步骤如下
- 导包
把import java.util.Scanner;放在最前面,相当于C语言中的引用头文件,这个包就相当于C语言中的头文件 - Scanner的实例化:Scanner scan = new Scanner(System.in);(具体的解释会放在面向对象的讲解中,目前先知道格式就行)
- 调用Scanner类的相关方法
示例:
class ScannerTest{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);//实例化Scanner类,scan就是它的一个对象
System.out.println("请输入你的姓名:");
String name = scan.next();//要求用户输入一个String型
System.out.println(name);
System.out.println("请输入你的芳龄:");
int age = scan.nextInt();//要求用户输入一个int型
System.out.println(age);
System.out.println("请输入你的体重:");
double weight = scan.nextDouble();//要求用户输入一个double型
System.out.println(weight);
System.out.println("你是否相中我了呢?(true/false)");
boolean isLove = scan.nextBoolean();//要求用户输入一个boolean型
System.out.println(isLove);
//对于char型的获取,Scanner没有提供相关的方法。只能获取一个字符串,但我们可以用charAt();这个方法来获取字符串中的字符
System.out.println("请输入你的性别:(男/女)");
String gender = scan.next();//输入男
char genderChar = gender.charAt(0);//获取索引为0位置上的字符,括号里的参数为获取字符的下标,下标从0开始,这个方法调用的格式先记着就好
System.out.println(genderChar);//结果为男
}
}
- 需要根据相应的方法,来输入指定类型的值。如果输入的数据类型与要求的类型不匹配时,会报异常:InputMisMatchException导致程序终止。
- 要接收int/short/long/float/double/byte型变量
可以使用nextInt/Short/Long/Float/Double/Byte();方法 - 没有接收char型变量的方法
- 接收String类型,使用next();或nextLine();方法
程序流程控制
- if-else语句
- switch-case语句
- for循环
- while循环
- do-while循环
这四种我们在C语言中都学习过,这里就不再赘述了- Java中的switch();在传参时可以传int,byte,short,char,String型变量,枚举类型变量!
- 如果判断的具体数值不多,而且符合 byte 、 short 、 char 、 int 、String 、枚举等几种类型.虽然两个语句都可以使用,建议使用swtich语句。因为效率稍高 。
- switch中case后面只能是具体的值,不能是取值范围
- 这里主要介绍下不同的地方,Java中没有goto语句!
但Java中有标签,Java 中的标签是为循环设计的,是为了在多重循环中方便的使用 break 和 coutinue 而设计的。正是由于这个原因,Java 的标签只能定义在三种循环 (for, do-while, while) 的开始位置,否则编译器会报告说找不到标签。在循环前面加上标签,就好像给循环起了个名字。而后在循环中使用 break 或者 continue 语句的时候,就可以带上这个标签做为参数,指明跳出 (break) 或者继续 (continue)标签对应的哪个循环。示例:
package check;
public class retryLearn {
static void retryContinue() {
System.out.println("执行retryContinue:");
int i = 0, j = 0;
retry:
for (i = 0; i < 2; i++) {
for (j = 0; j < 5; j++) {
System.out.println(j);
if (j == 3) {
continue retry;
}
}
}
System.out.printf("after loop, i = %d, j=%d", i, j);
}
static void retryBreak() {
System.out.println("执行retryBreak:");
int i = 0, j = 0;
retry1:
for (i = 0; i < 2; i++) {
for (j = 0; j < 5; j++) {
System.out.println(j);
if (j == 3) break retry1;
}
}
System.out.printf("after loop, i = %d, j=%d\n", i, j);
}
static void whileLabel() {
System.out.println("执行whileLabel:");
int i = 0;
int j = 0;
whileLabel:
while (i++ < 10) {
while (j < 10) {
System.out.println(j);
if (j == 6) break whileLabel;
++j;
}
}
System.out.printf("after loop, i = %d, j=%d\n", i, j);
}
public static void main(String[] args) {
retryContinue();
System.out.println("***********************");
retryBreak();
System.out.println("***********************");
whileLabel();
}
}
这里用了别的博主的东西,原文链接:Java中的goto
6. for-each,即增强for循环,我们会在学到数组的时候讲解,这里先放一放
三个方法的介绍
我们知道,C语言为我们提供了大量的函数,同样地,Java为我们提供了大量的方法,我们会在以后的学习中慢慢积累这些方法,在这里,我们先简要介绍三个方法
- Math.sqrt();
计算一个数的开平方,参数为一个double型数,返回值也是一个double型数 - Math.random();
Math.random()令系统随机选取大于等于 0.0 且小于 1.0 的伪随机double值,但每次运行这串随机数是相同的,有兴趣继续深挖的可以看这篇博文Math.random()的用法 - System.currentTimeMillis();
获取当前时间距离1970-01-01 00:00:00 的毫秒数,返回值类型为long