Java入门需要注意的一些问题
JRE和JDK
JRE:是java程序的运行环境,包含JVM和运行时所需要的核心类库。就是运行Java字节码的虚拟机
JDK:是java程序开发工具包,包括JRE和开发人员使用的工具。(编译器、调试等)
想要运行一个已有的Java程序(字节码文件),只需要安装JRE即可。想要开发一个全新的Java程序,就必须安装JDK。
如果只有java源码,就需要jdk。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
Java程序开发的三个步骤:
1.编写源程序(java源程序)
2.编译源程序(编译器)
翻译为Java字节码文件
3.运行(JVM运行)
第2步用javac.exe编译,第3步用java.exe运行
Java与其他编程语言的区别
高级语言翻译成机器语言有两种方式:编译和解释。
编译型语言:程序在执行之前需要一个专门的编译过程,把程序编译为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行。因此效率比较高,如:C、C++,代码是直接编译成机器码执行,但是不同的平台(x86、ARM等)CPU的指令集不同,因此需要编译出每一种平台的对应机器码
解释型语言:程序不需要编译,程序运行时才翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。如python,专门有一个解释器能够直接执行python程序,每个语句都是执行的时候才翻译。
而Java是介于编译型语言和解释型语言之间的,它是将代码编译成一种“字节码”,他类似于抽象的CPU指令,然后,针对不同平台编写虚拟机,不同平台的虚拟机负责加载字节码并执行,这样就实现了“一次编写,到处运行”的效果。当然,这是针对Java开发者而言。对于虚拟机,需要为每个平台分别开发。为了保证不同平台、不同公司开发的虚拟机都能正确执行Java字节码,SUN公司制定了一系列的Java虚拟机规范。从实践的角度看,JVM的兼容性做得非常好,低版本的Java字节码完全可以正常运行在高版本的JVM上。
数据类型的注意事项:
1.字符串String(首字母大写,并不是关键字)不是基本类型,而是引用类型
2.浮点型可能只是一个近似值,并非精确的值
3.数据范围与字节数不一定相关,例如float数据范围比long更加广泛,但是float是4字节,long是8字节。
4.浮点数当中默认类型是double。如果一定要使用float类型,需要加上后缀F。如果是整数,默认为int类型,如果要使用long类型,需要加上后缀L。推荐使用大写字母后缀。(如果不给后面加上大写字母,两种类型的二进制表现形式不同,可能会造成精度丢失)
给变量赋值时,右侧数值范围不能超过左侧数据类型的取值范围。
不同数据类型所占的字节数
例如:byte类型一共占一个字节、8位,首位位符号位、其余7位为数值为,那么范围为 -128(-1111111-1)~ 127(1111111-1)
-(2^7-1)-1 ~ (2^7)-1
浮点数可表示的范围非常大,float类型可最大表示3.4x1038,而double类型可最大表示1.79x10308。
Java语言对布尔类型的存储并没有做规定,因为理论上存储布尔类型只需要1 bit,但是通常JVM内部会把boolean表示为4字节整数。
数据类型转换:
byte->short->int->long->float->double(小->大)
自动类型转换(隐式):
1.特点:代码不需要进行特殊处理,自动完成
2.规则:数据范围从小到大
强制类型转换:
1.特点:代码需要进行特殊的格式处理,不能自动完成
2.格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据
注意事项:
强制类型转换一般不推荐使用,因为有可能发生精度损失(浮点转整型,不会四舍五入,所有小数位数会被舍弃掉),数据溢出
byte、short、char在进行四则运算时,都会先转成int类型,再进行运算(char类型则转为对应的Ascll码)
eg:
byte num1 = 40;
byte num2 = 50;
byte result = num1 + num2; //此处会报错,num1和num2会转成int类型,大的不能转成小的
System.out.println(result);
对于byte\short\char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将自动为我们补上(byte)(short)(char)。如果右侧超过了左侧范围,那么编译器直接报错。
byte num1 = 30; //右侧赋值时为int类型数字,但是没有超过左侧的范围,正确,编译器会隐含的执行(byte)进行转换
byte num2 = 128; //右侧超过左侧的范围会报错
char zifu1 = /*(char)*/65; //未超过范围输出不会报错
在给变量进行赋值的时候,如果右侧的表达式中全部都是常量,没有任何变量,那么编译器javac将会直接将若干个常量表达式计算得到结果。short = 5 + 8;中等号右边全是常量,没有任何变量参与运算,编译之后得到的.class字节码文件中相当于直接就是short result = 13;右侧的常量结果数值,没有超过左侧范围,所以正确。这称为“编译器的常量优化”。
short num1 = 5;
short num2 = 8;
short a = 5;
short result = num1 + num2; //此处会报错,num1和num2会转成int类型,大的不能转成小的
System.out.println(result);
short result1 = 5 + 8; //此处正确,有出入不用变量而是常量
System.out.println(result1);
short result2 = 5 + a + 8; //此处报错,其中不能有一个变量
System.out.println(result2);
要注意,超出范围的强制转型会得到错误的结果,原因是转型时**,int
的两个高位字节直接被扔掉,仅保留了低位的两个字节**,如下:
int i = 1234567;
short s = (short) i; // -10617
数字和字符的对照关系表(编码表):
ASCII:美国信息交换标准代码
Unicode:万国码,也是数字和符号的对照关系,开头的0-127部分和ASCII完全已有,但是从128开始包含更多字符。
char hanzi = '中';
System.out.println(hanzi + 0); //输出20013
运算符:(±*/%,自增/减,复合赋值、比较运算)
1.自增\自减:
使用方式:
1)单独使用:不和其他任何操作混合,自己独立成为一个步骤。
2)混合使用:和其他操作混合,eg:与赋值混合,或者与打印混合等。
使用区别:
1)单独使用时,前++和后++没有任何区别。也就是:++num和num++是完全一样的。
2)在混合使用时,有重大区别
a.如果是前++,那么变量立刻马上+1,然后拿着结果进行使用。(先加后用)
b.如果是后++,那么首先使用变量本来的数值,然后再让变量+1.(先用后加)
//与打印操作混合时
int num1 = 10;
//混合使用,先++立马变成11,然后打印结果11
System.out.println(++num1); //11
System.out.println(num1); //11
int num2 = 20;
//混合使用,后++先使用原变量num2,然后变量+1得到21
System.out.println(num2++); //20
System.out.println(num2); //21
当使用赋值操作混合时,和上面相同。
int x =10;
int y =20;
int result = ++x + y--;
System.out.println(result); //31
System.out.println(x); //11
System.out.println(y); //19
2.使用复合赋值运算时,里面会隐式的进行类型转换,如下:
byte num = 30;
num += 5;
//num = num + 5 --> num = byte + int --> num = int +int --> num = int
//num = (byte)int
System.out.println(num); //35
3.运算符类型
一元运算符:只需要一个数据就可以进行操作的运算符。如:!、++、–
二元运算符:需要两个数据才可以进行操作的运算符。如:+、-、=
三元运算符:需要三个数据才可以进行操作的运算符
格式: 数据类型 变量名称 = 条件判断 ? 表达式A:表达式B;
流程:首先判断条件是否成立,如果成立为true,那么将A赋给左侧变量;如果不成立为false,那么将B赋给左侧变量
//必须同时保证表达式A和B都符合左侧数据类型的要求
int a = 3 > 4 ? 2.5 : 10;
System.out.println(a); //错误写法,会报错,提示需要强制类型转换
4.注意事项:
1)一旦运算当中有不同类型的数据,那么结果将是数据类型范围大的那种。
2)任何数据类型和字符串进行连接时,结果都会变成字符串。
3)只有变量才能使用自增、自减运算符。常量不可发生变化,所以不能用。
4)复合赋值运算符(+=、-=、*=…)中隐含了一个强制类型转换。
5)比较运算中&&、||具有短路效果,如果根据左边已经可以判断得到最终结果,那么右边的代码将不再执行,从而节省一定的性能
6)三元运算符的 结果必须被使用(赋给变量,或者之间输出)
switch语句使用的注意事项:
1)多个case后面的数值不可以重复
2)switc后面的小括号中只能是下列数据类型:基本数据类型(byte\short\char\int)、引用数据类型(String\enum)
3)switch语句的格式可以很灵活,前后顺序可以颠倒,而且break语句可以省略(匹配哪一个case就从哪一个位置向下执行,直到遇到break或者整体结束为止)
从Java 12开始,switch语句升级为更简洁的表达式语法,使用类似模式匹配(Pattern Matching)的方法,保证只有一种路径会被执行,并且不需要break语句:
String fruit = "apple";
switch (fruit) {
case "apple" -> System.out.println("Selected apple");
case "pear" -> System.out.println("Selected pear");
case "mango" -> {
System.out.println("Selected mango");
System.out.println("Good choice!");
}
default -> System.out.println("No fruit selected");
}
注意新语法使用->,如果有多条语句,需要用{}括起来。不要写break语句,因为新语法只会执行匹配的语句,没有穿透效应。
使用新的switch语法,不但不需要break,还可以直接返回值。
String fruit = "apple";
int opt = switch (fruit) {
case "apple" -> 1;
case "pear", "mango" -> 2;
default -> 0;
}; // 注意赋值语句要以;结束
System.out.println("opt = " + opt);
for、while、do…while三种循环的区别:
for循环的变量在小括号中定义,只有循环内部可以使用,其他两个循环的初始话语句在外面,所以出来循环之后还可以使用。
for (int i =0;i<2;i++){
System.out.println(i);
}
System.out.println(i); //此处会报错
在Java中,while
循环是先判断循环条件,再执行循环。而另一种do while
循环则是先执行循环,再判断条件,条件满足时继续循环,条件不满足时退出。
Java的格式化功能提供的占位符
//一个整数格式化成十六进制,并用0补足8位
int n = 12345000;
System.out.printf("n=%d, hex=%08x", n, n); // 注意,两个%占位符必须传入两个数
方法
方法的三种调用格式:单独调用、打印调用(System.out.print(方法名(参数)))、赋值调用(数据类型 变量名称 = 方法名(参数))
方法的注意事项
1)返回值类型为void(无返回值)的方法只能单独调用,不能进行打印调用或者赋值调用。(可以写return;)
2)有返回值的方法,可以使用单独调用、打印调用或者赋值调用。
3)方法的定义在类中,但是不能在方法当中再定义方法,不能嵌套。
4)方法定义的前后顺序无所谓
5)一个方法中可以有多个return语句,但是必须保证同时只有一个会被执行到
方法重载
(方法名称相同<未限定修饰符>,但是参数列表不一样)
有关因素:参数个数不同、参数类型不同、参数的多类型顺序不同
无关因素:与参数名称无关、与返回值类型无关
/*1*/public static void open(){} //正确重载
/*2*/public static void open(int a){} //正确重载
/*3*/static void open(int a,int b){} //代码错误,和第8行冲突
/*4*/public static void open(double a,int b){} //正确重载
/*5*/public static void open(int a,double b){} //代码错误,和第6行冲突
/*6*/public void open(int i,double d){} //代码错误,和第5行冲突
/*7*/public static void OPEN(){} //代码正确,不会报错,但不是有效重载
/*8*/public static void open(int i,int j){} //代码错误,和第3行冲突
} //代码错误,和第8行冲突
/4/public static void open(double a,int b){} //正确重载
/5/public static void open(int a,double b){} //代码错误,和第6行冲突
/6/public void open(int i,double d){} //代码错误,和第5行冲突
/7/public static void OPEN(){} //代码正确,不会报错,但不是有效重载
/8/public static void open(int i,int j){} //代码错误,和第3行冲突