Java的基础语法
第一部分:
**
-
关键字
被Java语言赋予特定含义的单词,组成关键字的字母全部小写 -
标识符
就是给类,接口,方法,变量等起名字的字符序列 -
注释
用于解释说明程序的文字 -
常量
程序执行的过程中其值不可以发生改变 字面值常量 自定义常量(面向对象部分讲)
整数常量提供了4种表现形式
二进制,八进制,十进制,十六进制
进制转换有符号数据表示法 原码,反码,补码
符号位 数值位 -
变量
在程序执行的过程中,在某个范围内其值可以发生改变的量 -
数据类型
整数默认是int类型,浮点数默认是double。
长整数要加L或者l。
单精度的浮点数要加F或者f。 -
数据类型转化**
默认转换
A:从小到大
B:byte,short,char – int – long – float – double
C:byte,short,char之间不相互转换,直接转成int类型参与运算。
(1)下面的程序有问题吗,如果有,在哪里呢?
byte b1 = 3;
byte b2 = 4;
byte b3 = b1 + b2; //错误 类型提升了,b1和b2先转成int在运算,结果是int
byte b4 = 3 + 4; //正确 常量,先把结果计算出来,然后看是否在byte范围内,在就不报错
(2) byte b = (byte)130; 结果是 -126
System.out.println(b);
解释: 因为计算机中的运算都是补码进行的
130 的二进制是 00000000 00000000 00000000 10000010
这是130的原码,也是反码,也是补码
做截取操作,截取byte类型的了就是
100000010 这个结果是补码
已知补码求原码
符号位 数值位
补码 1 0000010
反码 1 0000001
原码 1 1111110 -
字符参与运算(ASCII值运算),字符串参与运算(+号代表字符串连接符)
第二部分
-
运算符
(1)算术运算符
例1 int x=3;
int y=4;
如果我就像得到小数,只需要把操作的数据中任意的一个数据变为浮点数
System.out.println(x1.0/y);
例2 int x = 4;
int y = (x++)+(++x)+(x10);
//4+6+60
//x=5,6
+的用法:
A:加法
B:正号
C:字符串连接符(2)赋值运算符
面试题:
short s = 1;
s = s + 1
short s = 1;
s += 1;
请问上面的代码哪个有问题?
为什么第二个木有问题呢? 第一个short类型参与运算转化为int
扩展的赋值运算符其实隐含了一个强制类型转换。
s += 1;
不是等价于 s = s + 1;
而是等价于 s = (s的数据类型)(s + 1);(3)比较运算符 int a = 10;
int b = 20;//boolean flag = (a == b); //boolean flag = (a = b); //这个是有问题的,不兼容的类型 //System.out.println(flag); int c = (a = b); //把b赋值给a,然后把a留下来 System.out.println(c); //20
(4)逻辑运算符 &:有false则false
|:有true则true
^:相同则false,不同则true。
情侣关系。
!:非true则false,非false则true&&:结果和&是一样的,只不过有短路效果。左边是false,右边不执行。 ||:结果和|是一样的,只不过有短路效果。左边是true,右边不执行。
例1
int x = 3;
int y = 4;
//boolean b1 = ((x++ == 3) & (y++ == 4)); 4,5,true
//boolean b1 = ((x++ == 3) && (y++ == 4)); 4,5,true
//boolean b1 = ((++x == 3) & (y++ == 4)); 4,5,false
boolean b1 = ((++x == 3) && (y++ == 4)); 4,4,false
System.out.println("x:"+x);
System.out.println("y:"+y);
System.out.println(b1);
(5)位运算符 位运算符:
&,|,^,~ 两边是数值时是位运算,boolean时是逻辑运算
<<,>>,>>>
注意:例题
要做位运算,首先要把数据转换为二进制。
int a = 3;
int b = 4;
System.out.println(3 & 4);
System.out.println(3 | 4);
System.out.println(3 ^ 4);
System.out.println(~3);
分析:因为是位运算,所以我们必须先把数据换算成二进制。
3的二进制:11
00000000 00000000 00000000 00000011
4的二进制:100
00000000 00000000 00000000 00000100
&位与运算:有0则0。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000000
结果是:0
|位或运算:有1则1。
00000000 00000000 00000000 00000011
|00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
^位异或运算:相同则0,不同则1。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
~按位取反运算符:0变1,1变0
00000000 00000000 00000000 00000011
~11111111 11111111 11111111 11111100 (补码)
补码:11111111 11111111 11111111 11111100
反码:11111111 11111111 11111111 11111011
原码:10000000 00000000 00000000 00000100
结果是:-4
例二
^的特点:一个数据对另一个数据位异或两次,该数本身不变。
int a = 10;
int b = 20;
System.out.println(a ^ b ^ b); //10
System.out.println(a ^ b ^ a); //20
面试题:
请自己实现两个整数变量的交换
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b);
//方式1:使用第三方变量(开发中用的)
/*
int c = a;
a = b;
b = c;
System.out.println("a:"+a+",b:"+b);
System.out.println("------------");
*/
//方式2:用位异或实现(面试用)
//左边:a,b,a
//右边:a ^ b
/*
a = a ^ b;
b = a ^ b; //a ^ b ^ b = a
a = a ^ b; //a ^ b ^ a = b
System.out.println("a:"+a+",b:"+b);
*/
//方式3:用变量相加的做法
/*
a = a + b; //a=30
b = a - b; //b=10
a = a - b; //a=20
System.out.println("a:"+a+",b:"+b);
*/
//方式4:一句话搞定
b = (a+b) - (a=b); //b=30-20=10,a=20
System.out.println("a:"+a+",b:"+b);
1
<<:左移 左边最高位丢弃,右边补齐0
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移 无论最高位是0还是1,左边补齐0
>>> 无符号右移 3>>>1=1—>3/1=1
//<< 把<<左边的数据乘以2的移动次幂
System.out.println(3 << 2); //3*2^2 = 3*4 = 12;
//>> 把>>左边的数据除以2的移动次幂
System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6
System.out.println(24 >>> 2);
System.out.println(-24 >> 2); //-6
System.out.println(-24 >>> 2);
计算出3的二进制:11
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 0000001100
>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) 补码
补码:1111111111 11111111 11111111 111010
反码:1111111111 11111111 11111111 111001
原码:1000000000 00000000 00000000 000110
结果:-6
>>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00)
结果: 1073741818
面试题:
请用最有效率的方式写出计算2乘以8的结果?
2 * 8
2 << 3
(6)三目运算符
比较表达式?表达式1:表达式2;
B:执行流程:
根据比较表达式的计算返回一个true或者false。
如果是true,表达式1就是结果。
如果是false,表达式2就是结果。
面试题
int z = ((x = y)? x : y); //报错 因为 比较表达式的结果是一个boolean类型。
X=y;相当于把y值赋给x,x是int类型,而比较表达式需要的是boolean类型
案例:
a:比较两个数据是否相等
int max = (x > y? x: y);
b:获取两个数据中的最大值
int max2 = (a > b)?((a > c)? a: c)?(b > c)? b: c);
c:获取三个数据中的最大值
boolean flag = (m == n);
2. 键盘录入
那么,我们如何实现键盘数据的录入呢?
A:导包
格式:
import java.util.Scanner;
位置:
在class类的上面。
B:创建键盘录入对象
格式:
Scanner sc = new Scanner(System.in);
C:通过对象获取数据
格式:
int x = sc.nextInt();
-
流程控制语句
(1)顺序结构 (2)选择结构 if语句
所有的三元运算符能够实现的,if语句的第二种格式都能实现。
反之不成立。如果if语句第二种格式控制的语句体是输出语句,就不可以。 因为三元运算符是一个运算符,必须要有一个结果返回,不能是一个输出语句。
例1 int max1;
if(a > b) {
max1 = a;
}else {
max1 = b;
}
System.out.println(“max1:”+max1);
//用三元改进
int max2 = (a > b)? a: b;
System.out.println("max2:"+max2);
System.out.println("----------");
//判断一个数据是奇数还是偶数,并输出是奇数还是偶数
int x = 100;
if(x%2 == 0) {
System.out.println("100是一个偶数");
}else {
System.out.println("100是一个奇数");
}
//用三元改进
//这种改进是错误的。
//String s = (x%2 == 0)?System.out.println("100是一个偶数"):System.out.println("100是一个奇数");
例2 获取三个数据中的最大值
//三元实现
//int temp = (a>b)? a: b;
//int max = (temp>c)? temp: c;
//System.out.println(“max:”+max);
//System.out.println("--------");
//用if语句实现
int max;
if(a > b) {
if(a > c) {
max = a;
}else {
max = c;
}
}else {
if(b > c) {
max = b;
}else {
max = c;
}
}
System.out.println("max:"+max);
Switch语句
switch语句的表达式可以是byte吗?可以是long吗?可以是String吗?
可以,不可以,JDK7以后可以
A:case后面只能是常量,不能是变量,而且,多个case后面的值不能出现相同的
B:default可以省略吗?
可以省略,但是不建议,因为它的作用是对不正确的情况给出提示。
特殊情况:
case就可以把值固定。
A,B,C,D
C:break可以省略吗?
可以省略,但是结果可能不是我们想要的。
会出现一个现象:case穿透。
最终我们建议不要省略
D:default一定要在最后吗?
不是,可以在任意位置。但是建议在最后。
E:switch语句的结束条件
a:遇到break就结束了
b:执行到末尾就结束了
例1
int x = 2;
int y = 3;
switch(x){
default:
y++;
break;
case 3:
y++;
case 4:
y++;
}
System.out.println(“y=”+y); //y=4
System.out.println("---------------");
int a = 2;
int b = 3;
switch(a){
default:
b++;
case 3:
b++;
case 4:
b++;
}
System.out.println("b="+b); // b=6
int choiceNumber = 65;
//强制转换为字符类型
char choice = (char) choiceNumber;// choice则是A
选择结构(各自使用场景) if语句使用场景: 针对结果是boolean类型的判断 针对一个范围的判断 针对几个常量值的判断 switch语句使用场景: 针对几个常量值的判断
(3)循环结构
while循环和for循环的区别?
使用区别:如果你想在循环结束后,继续使用控制条件的那个变量,用while循环,否则用for循环。不知道用for循环。
因为变量及早的从内存中消失,可以提高内存的使用效率。
其实还有一种场景的理解:
如果是一个范围的,用for循环非常明确。
如果是不明确要做多少次,用while循环较为合适。
举例:吃葡萄。
注意:
‘\x’ x表示任意,这种做法叫转移字符。
'\t' tab键的位置
'\r' 回车
'\n' 换行
(4)跳转控制语句
(1)break:中断的意思
A:用在循环和switch语句中,离开此应用场景无意义。
B:作用
a:跳出单层循环
b:跳出多层循环,需要标签语句的配合
(2)continue:继续
A:用在循环中,离开此应用场景无意义。
B:作用
a:跳出单层循环的一次,可以继续下一次
C:填空题
for(int x=1; x<=10; x++) {
if(x%3 == 0) {
//补齐代码
}
System.out.println(“Java基础班”);
}
如何让控制台输出2次:Java基础班
如何让控制台输出7次:Java基础班
如何让控制台输出13次:Java基础班
(3)return:返回
A:用于结束方法的,后面还会在继续讲解和使用。
B:一旦遇到return,程序就不会在继续往后执行。
第三部分
-
方法
没有明确返回值的函数调用: 其实就是void类型方法的调用 只能单独调用
方法重载
概述:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。 方法重载特点:与返回值类型无关,只看方法名和参数列表 在调用时,虚拟机通过参数列表的不同来区分同名方法 -
数组
数组的初始化方式 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。 静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
不要同时动态和静态同时进行,如:int[]arr = new int [3]{1,2,3}; // 错误定义第三个数组,把第一个数组的地址值赋值给它。(注意类型一致),通过第三个数组的名称去把元素重复赋值。
//定义第三个数组
int[] arr3 = arr;
arr3[0] = 100;
arr3[1] = 200;
System.out.println(arr);
System.out.println(arr[0]); //值发生改变了
System.out.println(arr[1]); //值发生改变了
System.out.println(arr[2]);
栈内存的两个引用指向同一个内存空间。无论是它们谁的操作,都是针对同一个地方数组的常见操作
A:遍历方式1:
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
System.out.println(arr[x]);
}
}方式2: public static void printArray(int[] arr) { System.out.print("["); for(int x=0; x<arr.length; x++) { if(x == arr.length-1) { System.out.println(arr[x]+"]"); }else { System.out.println(arr[x]+", "); } } } B:最值 最大值: public static int getMax(int[] arr) { int max = arr[0]; for(int x=1; x<arr.length; x++) { if(arr[x] > max) { max = arr[x]; } } return max; } 最小值: public static int getMin(int[] arr) { int min = arr[0]; for(int x=1; x<arr.length; x++) { if(arr[x] < min) { min = arr[x]; } } return min; } C:逆序 方式1: public static void reverse(int[] arr) { for(int x=0; x<arr.length/2; x++) { int temp = arr[x]; arr[x] = arr[arr.length-1-x]; arr[arr.length-1-x] = temp; } } 方式2: public static void reverse(int[] arr) { for(int start=0,end=arr.length-1; start<=end; start++,end--) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; } } D:查表 public static String getString(String[] strArray,int index) { return strArray[index]; } E:基本查找 方式1: public static int getIndex(int[] arr,int value) { for(int x=0; x<arr.length; x++) { if(arr[x] == value) { return x; } } return -1; } 方式2: public static int getIndex(int[] arr,int value) { int index = -1; for(int x=0; x<arr.length; x++) { if(arr[x] == value) { index = x; break; } } return index; }
-
二维数组
(1) int [] x,y[]; // x是一个一维数组,y是一个二维数组
(2) 格式2:
数据类型[][] 数组名 = new 数据类型[m][];
m:表示这个二维数组有多少个一维数组。
列数没有给出,可以动态的给。这一次是一个变化的列数。
int[][] arr = new int[3][];
System.out.println(arr); //[[I@175078b
System.out.println(arr[0]); //null
System.out.println(arr[1]); //null
System.out.println(arr[2]); //null
//动态的为每一个一维数组分配空间
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
System.out.println(arr[0]); //[I@42552c
System.out.println(arr[1]); //[I@e5bbd6
System.out.println(arr[2]); //[I@8ee016
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//ArrayIndexOutOfBoundsException
//System.out.println(arr[0][2]); //错误
arr[1][0] = 100;
arr[1][2] = 200;
(3)需求:二维数组遍历
外循环控制的是二维数组的长度,其实就是一维数组的个数。
内循环控制的是一维数组的长度。
//定义一个二维数组
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
(4) 杨辉三角形
需求:打印杨辉三角形(行数可以键盘录入)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
分析:看这种图像的规律
A:任何一行的第一列和最后一列都是1
B:从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
步骤:
A:首先定义一个二维数组。行数如果是n,我们把列数也先定义为n。
这个n的数据来自于键盘录入。
B:给这个二维数组任何一行的第一列和最后一列赋值为1
C:按照规律给其他元素赋值
从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
D:遍历这个二维数组。
Scanner sc = new Scanner(System.in);
//这个n的数据来自于键盘录入。
System.out.println(“请输入一个数据:”);
int n = sc.nextInt();
//定义二维数组
int[][] arr = new int[n][n];
//给这个二维数组任何一行的第一列和最后一列赋值为1
for(int x=0; x<arr.length; x++) {
arr[x][0] = 1; //任何一行第1列
arr[x][x] = 1; //任何一行的最后1列
}
//按照规律给其他元素赋值
//从第三行开始,每一个数据是它上一行的前一列和它上一行的本列之和。
for(int x=2; x<arr.length; x++) {
//这里如果y<=x是有个小问题的,就是最后一列的问题
//所以这里要减去1
//并且y也应该从1开始,因为第一列也是有值了
for(int y=1; y<=x-1; y++) {
//每一个数据是它上一行的前一列和它上一行的本列之和。
arr[x][y] = arr[x-1][y-1] + arr[x-1][y];
}
}
//这个时候,要注意了,内循环的变化必须和曾经讲过的九九乘法表类似
for(int x=0; x<arr.length; x++) {
for(int y=0; y<=x; y++) {
System.out.print(arr[x][y]+"\t");
}
System.out.println();
}
}
Java中的参数传递问题:
基本类型:形式参数的改变对实际参数没有影响。 // Change(int a,int b)
引用类型:形式参数的改变直接影响实际参数。 // Change(int[] arr)
(5) //把数组的元素拼接成一个字符串返回
//定义一个空内容字符串
String s = “”;
for(int x=0; x<index; x++) {
s += arr[x];
}
return s;