文章目录
Java语言基础
1.跨平台原理
Java语言之所以流行,与它具有很多优点有关。Java最大的优点就是跨平台(编译后的生成的字节码文件可以跨平台运行)。Java的跨平台可以使用8个字概括:一次编译,到处运行;
1、Java程序的运行要经过编辑、编译、解释并执行三个阶段。
2、Java源代码经过编译生成字节码文件(.class)。字节码文件与平台无关,不面向任何具体平台,只面向虚拟机。
3、字节码文件需要解释成相应平台的机器码并运行。解释是通过Java虚拟机来执行的。Java虚拟机是可运行Java字节码文件的虚拟计算机。Java虚拟机(中的Java解释器)负责将字节码文件解释成为特定的机器码来运行。不同平台的虚拟机是不同的,但它们都提供了相同的接口。
2.八种基本数据类型
对于上图有以下几点需要注意:
- java八种基本数据类型分为四类八种,四类分别为整型、浮点型、布尔型、字符型;八种分别为byte、short、int、long、float、double、boolean、char;
- java八种基本数据类型的字节数:分别为1、2、4、8个字节;1字节(byte、boolean)、 2字节(short、char)、4字节(int、float)、8字节(long、double);
- 整数的默认类型为int,浮点数的默认类型为double;
- 八种基本数据类型的包装类:除了char的是Character、int类型的是Integer,其他都是首字母大写
- 关于值的范围问题,需要注意char类型是无符号的,不能为负,所以是0开始的;
浮点数,在通常情况下,应该使用double型,因为比float型更精确。
浮点数使用陷阱:2.7和8.1/3比较
double num1 = 2.7;
double num2 = 8.1/3;
// 得到一个重要的使用点: 当我们对运算结果是小数的进行相等判断是,要注意
// 应该是以两个数的差值的绝对值,在某个精度范围内类判断
if (Math.abs(num1 - num2) < 0.000001) System.out.println("相等");
在java中,char的本质是一个整数,在输出时,是unicode码对应的字符。
- 整数型的直接量默认为int类型
- 浮点型的直接量默认为double类型
3.基本数据类型转换
自动类型转换:
当java程序在进行赋值或运算时,精度小的类型会自动转换为精度大的数据类型,数据类型按精度(容量)大小排序为
自动类型转换注意和细节
- 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
- 当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据类型时,就会报错,反之就会进行自动类型转换。
byte、short、char
之间不会相互自动转换。byte、short、char
他们三者可以计算,在计算时首先转换为int类型。- 如果把
int
转换成float
,或者long
转换成double
,不需要强制转换,但可能丢失精度。 float
和double
是属于近似值,byte,char,short,int,long
属于精确值,精确值转近似值时可能丢失精度。- 如果用于表示货币,不建议使用
float,double
- boolean不参与转换。
- 自动提升原则:表达式结果的类型自动提升为操作数中最大的类型。
强制转换:
高等级转为低等级的时候,必须强制转换,但实际工作中不推荐使用强制转换,可能会失精度或数据溢出;
相关面试题:
-
类型转换
public static void main(String[] args) { int a=10; double b=3.4; System.out.println(a>b?a:b); System.out.println(a); } /*输出:10.0 10 解析:这里是一个很容易让人不注意的类型转化,这里a与b参与了运算, 所以类型向类型大的方向转化,10就变成了10.0,但是a本身是没有变化的*/
-
+=情况
public static void main(String[] args) { short a=1; //第一行 a=a+1; //第二行 a+=1; //第三行 } /*第几行的代码会出错? 答案:第二行会出错,由于a+1变为了int类型,而int类型不能直接赋值给short类型 但是+=这种情况是特殊的,所以不会出错; */
-
自动装箱
-
包装类和基本数据类型比较时,只要值相等就相等
public static void main(String[] args) { Integer a1=127; Integer a2=127; int a3=127; Integer b1=128; Integer b2=128; int b3=128; System.out.println(a1==a2); System.out.println(a1==a3); System.out.println(b1==b2); System.out.println(b1==b3); } /*输出:true true false true 解析:自动装箱时采用valueOf方法,由于127在静态数组的范围内,所以不是new的, 而128的两个引用是指向new出现对象的,所以第一个是true,第三个是false。 而包装类和基本数据类型比较时,只要数值是相等的,就相等 */
- char类型存储汉字
char类型能不能存储一个汉字?为什么?
解析:能,char类型采用的是Unicode编码,Unicode编码包含汉字,所以char类型自然是可以存储一个汉字的
-
浮点数精度问题
public static void main(String[] args) { System.out.println(0.1*3==0.3); System.out.println(0.1*4); } /*输出:false 0.4 解析:有些浮点数不能准确的表示出来,与整数相乘之后出精度丢失,常见为小数位含3的 */
4.关键字
5.运算符
(1)算术运算符
- 对于除号
/
,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。如:int x = 10/3;
结果为3。 - 当对一个数取模时,可以等价
a%b = a - a/b * b
。 - 当自增做一个独立语言使用时,不管是
++i
还是i++
都是一样的,等价。
使用位移的方法是最快的
左移算法:位移数作为2的次幂与操作数相乘
右移算法:操作数除以位移数的2次幂
不通过第三个变量如何交换两个数
通过表达式
int a = 1, b = 2;
a = a + b - (b=a);
通过加减
int a = 1, b = 2;
a = a + b;
b = a - b;
a = a - b;
通过异或,这是最快的方法(a不等于b)
int a = 1, b = 2;
a = a^b;
b = a^b;
a = a^b;
(2)关系运算符
(3)逻辑运算符
**&&和&**使用区别:
- **&&**短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为false,效率高
- **&**逻辑与:不管第一个条件是否为 false,第二个条件都要判断,效率低
|| 与 | 区别:
- 如果 a 为 true,则不计算 b (因为不论 b 为何值,结果都是 true)
运算符的优先级
面试题:
int i = 1
i = i++;
System.out.println(i); // 结果是多少,为什么 1
int i = 1
i = ++i;
System.out.println(i); // 结果是多少,为什么 2
6.Switch注意事项
- 表达式数据类型,应和case 后的常量类型一致,或者是可以自动转成可以互相比较的类型,如输入的是字符,而常量是int
- switch(表达式)中表达式的返回值必须是:(byte,short,int,char,enum,String)
- case 子句中的值必须是常量,而不能是变量
- default子句是可选的,当没有匹配的case时,执行default
- break语句用来在执行完一个case分支后使程序跳出switch块;如果没有写break,程序会顺序执行到switch结尾,除非遇到break
7.方法的重载
在同一个类中,方法名相同,参数列表不同,返回值不能作为重载的条件
8.数组
数组的遍历:
- for循环
- foreach
注意:在for(int n : ns)循环中,变量n直接拿到ns数组的元素,而不是索引。
显然 foreach 循环更简洁。但是 foreach 循环无法拿到数组的索引
JDK1.5可变参数,可变参数只能是参数列表中的最后一个,可变参数作为数组使用
print(25,2,9,45,23,4,5,3,7);
public static void print(int... x){
int len = x.length;
for(int i = 0;i < len; i++)
System.out.println(x[i]);
}
空指针异常:当一个变量为null
没有赋值时,去调用了该变量的属性和方法
注意:
- 数组是多个相同类型数据的组合,实现对这些数据的统一管理。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
- 数组创建后,如果没有赋值,有默认值 int 0,short 0,byte 0,long 0,float 0.0,double 0.0,char \u0000,boolean false,String null
- 使用数组的步骤:1.声明数组并开辟空间 2.给数组各个元素赋值 3.使用数组
- 数组的下标是从 0 开始的。
- 数组下标必须在指定范围内使用,否则报:下标越界异常,比如 int [] arr = new int[5]; 则有效下标为 0-4
- 数组属引用类型,数组型数据是对象(object)
数组赋值机制
基本数据类型赋值,就是值传递,互不影响
数组在默认情况下是引用传递,赋的是地址
9.排序
排序介绍:
-
内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择 式排序法和插入式排序法)
-
外部排序:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)
Arrays类
Arrays工具类:用来操作数组(比如排序和搜索)的各种方法
常用方法:
- 使用二分法查找
Arrays.binarySearch(int[] array, int value);
- 数组内容转成字符串的形式输出
Arrays.toString(int[] array);
- 数组排序
Arrays.sort(int[] array);
- 复制指定的数组
Arrays.copyOf(int[] array, int length);
Arrays.copyOf(int[] array, int from, int to);
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
arraycopy
性能高于copyOf
,因为copyOf
的源码实现就是使用arraycopy
- 判断两个数组是否相等
Arrays.equels();
- 使用指定元素填充数组
Arrays.fill();