1.1 关键字、保留字
- 关键字:被java赋予特殊含义的字符串。
- 官方规范中有50个关键字
- true、false、null虽然不是关键字,但是可以当做关键字来看待。
- 保留字:goto、const
1.2 标识符
- 标识符:凡是可以自己命名的地方,都是标识符。
- 比如:类名、变量名、方法名、接口名、包名、常量名等。
- 记住:标识符命名的规则(必须要遵守的,否则编译不通过)
>有26个英文字母大小写,0-9,_或$组成
>数字不可以开头。
>不可以使用关键字和保留字,但能包含关键字和保留字。
>Java中严格区分大小写,长度无限制。
>标识符不能包含空格。
- 标识符的命名规范(建议遵守。如果不遵守,编译和运行都能正常执行。只是容易被人鄙视)
>包名:多单词组成时所有字母都小写:xxxyyyzzz。
例如:java.lang、com.atguigu.bean
>类名、接口名:多单词组成时,所有单词的首字母大写;XxxYyyZzz
例如:HelloWorld,String,System等
>变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
例如:age,name,bookName,main,binarySearch,getName
>常量名:所有字母都大写。多单词时每个单词用下划线连接:xxx_yyy_zzz
例如:MAX_VALUE,PI,DEFAULT_CAPACITY
- "见名知意"
/*
1.什么是标识符?Java中变量、方法、类等要素命名时使用的字符序列,称为标识符。
技巧:凡是自己可以起名字的地方都叫标识符。比如:类名、方法名、变量名、包名、常量名等
2.标识符的命名规则(必须遵守!!否则,编译不通过)
3.标识符的命名规范
说明:大家在定义标识符时,要注意"见名知意"
*/
class Identifier
{
public static void main(String[] args){
int abc =12;
int age =12; //age:标识符
int myAge =12;
char gender = '男';
//不推荐写法
//int myAge =12;
System.out.println(myAge);
}
public static void main1(String[] args){
}
}
class _a$b
{
}
class 1_ab{
}
class public
{
}
class publicstring
{
}
1.3 变量的基本使用(重点)
- 1.变量的理解:
内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化
- 2.变量的构成包含三个要素:
数据类型、变量名、存储的值
- 3.Java中变量声明的格式:
数据类型 变量名 = 变量值
- 4.定义变量时,变量名要遵守标识符命名的规则和规范。
- 5.说明:
① 变量都有其作用域。变量只在作用域内是有效的,出了作用域就失效了。
② 在同一个作用域内,不能声明两个同名的变量。
③ 定义好变量以后,就可以通过变量名的方式对变量进行调用和运算。
④ 变量值在赋值时,必须满足变量的数据类型,并且在数据类型有效的范围内变化。
class VariableTest {
public static void main(String[] args) {
//定义变量的方式1:
char gender; //过程1:变量的声明
gender = '男'; //过程2:变量的赋值(或初始化)
gender = '女';
//定义变量的方式2:声明与初始化合并
int age = 10;
System.out.println(age);
System.out.println("age = " + age);
System.out.println("gender = " + gender);
//在同一个作用域内,不能声明两个同名的变量
//char gender = "女";
gender = '男';
System.out.println("gender = " + gender);
//由于number前没有声明类型,即当前number变量没有提前定义。所以编译不通过。
//number = 10
byte b1 =127;
//b1超出了byte的范围,编译不通过
//b1 = 128
}
public static void main123(String[] args){
//变量gender超出了作用域 -==-
//System.out.println("gender = " + gender);
}
}
1.4 基本数据类型变量的使用(重点)
- 1.Java中的变量按照数据类型来分类:
基本数据类型(8种):
整形:byte \ short \ int \ long\
浮点型:float \ double
字符型:char
布尔型:boolean
引用数据类型:
类(class)
数组(array)
接口(interface)
枚举(enum)
注解(annotation)
记录(record)
1.5 基本数据类型变量间的运算规则(重点)
1.5.1 自动类型提升
- 测试基本数据类型变量间的运算规则
- 这里提到可以做运算的基本类型有7种,不包含boolean类型。
- 运算规则包括:
①自动类型提升
②强制类型转换 - VariableTest.java用来测试自动类型提升
- 规则:
当容量小的变量与容量大的变量做运算时,结果自动转换为容量大的数据类型。
byte、short、char ----> int ----> long ----> float -----> double
特别的:byte、short、char类型的变量之间做运算,结果为int类型
说明:此时容量或大或小,并非指占用的内存空间的大小,而是指表示数据的范围的大小。
long(8字节)表示数据范围小于float(4字节)
class VariableTest3 {
public static void main(String[] args) {
int i1 = 10;
int i2 = i1;
long l1 = i2;
float f1 = l1;
byte b1 = 12;
byte b2 = 12;
int i3 = b1 + i1;
//不兼容的类型: 从int转换到byte可能会有损失
//byte b2 = b1 + i1;
//****************************************
//特殊情况1:byte、short、char之间做运算,默认为int类型做运算
//不兼容的类型: 从int转换到byte可能会有损失
//byte b3 = b1 + b2;
byte b3 = 12;
short s1 = 12;
//不兼容的类型: 从int转换到byte可能会有损失
//byte b4 = b3 + s1;
int i4 =b3 + s1;
//特殊情况2:char
char c1 = 'a';
//不兼容的类型: 从int转换到char可能会有损失
//char c2 = c1 + b1;
//****************************************
//练习1:
long l2 = 123L;
long l3 = 123;// 编译可以通过,理解为自动类型提升 (int ------>long)
//错误: 整数太大,理解为int类型,因为超出了int范围,所以会报错。
//long l4 = 123123123123;
long l5 = 123123123123L;//此时的123123123123L就是使用8个字节存储的long类型的值
//练习2:
float f2 = 12.3F;
//不兼容的类型: 从double转换到float可能会有损失,默认的浮点数为double类型
//float f3 = 12.3;
//练习3:
//规定:整形常量,默认规定是int类型。
byte b4 = 10;
//不兼容的类型: 从int转换到byte可能会有损失
//byte b5 = b4 + 1;
//规定2:浮点型常量,默认规定是double类型。
double d1 = b4 + 12.3;
//练习4:说明为什么不允许变量名是数字开头的。为了"自洽"
//错误: 不是语句
/*
int 123L = 23;
long l6 = 123L;
*/
}
}
1.5.2 强制类型转换
- 规则:
- 如果需要将容量达到变量的类型转换为容量小的变量的类型,需要使用强制类型转换
- 强制类型转换需要使用墙砖符:()。
- 强制类型转换过程中,可能导致精度损失。
class VariableTest4{
public static void main(String[] args){
double d1 = 12;
int i1 = (int)d1;
System.out.println(i1); //打印12
long l1 =123L;
short s1 = (short)l1;
System.out.println(s1);//打印123
//练习
int i2 = 12;
float f1 = i2;//(自动类型提升)
System.out.println(f1);//打印12.0
float f2 = (float)i2;//编译可以通过,只不过可以省略()。
//精度损失的例子1:
double d2 = 12.9;
int i3 = (int)d2;
System.out.println(i3);//截断,不是四舍五入,打印12
//精度损失的例子2:
int i4 = 128;
byte b1 = (byte)i4;
System.out.println(b1);//打印-128
//实际开发举例:
byte b2 =12;//int num = b2;自动类型提升
method(b2);//打印num + 12
long l2 = 12L;
method((int)l2);//打印num + 12
}
public static void method(int num){
System.out.println("num + " + num);
}
}
1.6 String类的使用、与基本数据类型变量间的运算
- String的认识:字符串。使用一对""表示,内部包含0个、1个或多个字符。
- String与8种基本数据类型变量间的运算:+ (连接)。运算的结果是String类型。
- 一、关于String的理解
- String类,属于引用数据类型,俗称字符串。
- String类型的变量,可以使用一对""的方式进行赋值。
- String声明的字符串内部,可以包含0个,1个或多个字符。
- 二、String与基本数据类型变量间的运算
- 这里的基本数据类型包含boolean在内的8种。
- String与基本数据类型变量间只能做连接运算,使用"+"表示
- 运算的结果是String类型。
class StringTest{
public static void main(String[] args) {
String str1 = "Hello World!";
System.out.println("str1"); //打印 str1
System.out.println(str1); //打印 Hello World!
String str2 = "";
String str3 = "a";//与char c1 = 'a';的区别,一个是引用数据类型,一个是基本数据类型。除了是a,没有共同点
//测试连接运算
int num1 = 10;
boolean b1 = true;
String str4 = "hello";
System.out.println(str4 + b1);// 打印hellotrue
String str5 = str4 + b1;
String str6 = str4 + b1 + num1;
System.out.println(str6);//打印hellotrue10
//思考:如下的声明编译能通过吗?
//String str7 = b1 + num1 +str4;//基本数据类型能做运算的只有7种,不包含boolean类型。当boolean类型+int类型时,这里的"+"不是连接的作用,是运算的作用,连接作用只在String类型的运算中。
//如何将String类型的变量转换为基本数据类型?
String str8 = "abc";//不能考虑转换为基本数据类型的。
int num2 = 10;
String str9 = num2 + "";//"10"
//不兼容的类型: String无法转换为int
//int num3 = (int)str9;
//如何实现呢?使用Integer类。
int num3 = Integer.parseInt(str9);
System.out.println(num3 + 1);//打印11
}
}
- 练习1:
- 要求填写自己的姓名、年龄、性别、体重、婚姻状况(已婚用true表示,单身用false表示)、联系方式等等。
/*
要求填写自己的姓名、年龄、性别、体重、婚姻状况(已婚用true表示,单身用false表示)、联系方式等等。
*/
class StringExer{
public static void main(String[] args) {
String name = "油条不是老油条";
int age = 23;
char gengder = '女';
double weight = 98.3;
boolean isMarried = false;
String phoneNumber = "154282824399";
System.out.println("name = " + name + ";age = " + age + ";gengder = " + gengder + ";weight = "+ weight + ";isMarried = " + isMarried);
}
}
- 练习2:
class StringExer1{
public static void main(String[] args) {
//练习1:
//String str1 = 4; //这里String类型要加"",没有加就会报错
String str2 = 3.5f + "";
System.out.println(str2); //打印3.5,因为3.5f表示float类型,所以不会打印3.5f
System.out.println(3 + 4 + "Hello!"); //打印 7Hello!
System.out.println("Hello!" + 3 + 4); //打印Hello!34
System.out.println('a' + 1 + "Hello!"); //打印98Hello!
System.out.println("Hello" + 'a' + 1); //打印Helloa1
//练习2:
System.out.println("* *"); //输出* *
System.out.println("*\t*"); //输出* *
System.out.println("*" + "\t" + "*"); //输出* *
System.out.println('*' + "\t" + "*"); //输出* *
System.out.println('*' + '\t' + "*"); //输出51*
System.out.println("*" + '\t' + '*'); //输出* *
System.out.println('*' + "\t" + '*'); //输出* *
System.out.println("*" + "\t" + '*'); //输出* *
System.out.println('*' + '\t' + '*'); //输出93
}
}
1.7 常识:进制的认识
- 熟悉:二进制(以0B或0b开头)、十进制、八进制(以0开头)、十六进制(以0x或0X开头)的声明方式。
- 二进制的理解
- 正数:原码、反码、补码三码合一。
- 负数:原码、反码、补码不相同。以1开头的一定是补码。了解三者关系,原码取反为反码,反码+1为补码。
- 计算机的底层是以补码的方式存储数据的。
- 熟悉:二进制与十进制之间的转换
- 了解:二进制与八进制、十六进制间的转换
class BinaryTest{
public static void main(String[] args) {
int num1 = 123;
int num2 = 0b1010;
int num3 = 0123;
int num4 = 0x123;
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
System.out.println(num4);
}
}
1.8 运算符(较常用的是重点)
1.8.1算术运算符
-
+ - * / % (前)++ (后)++ (前)-- (后)-- +(连接)
class AriTest{
public static void main(String[] args) {
//********************************
//除法:
int m1 = 12;
int n1 = 5;
int k1 = m1 / n1;
System.out.println(k1);//输出2(截断)
System.out.println(m1 / n1 * n1);//输出10
//********************************
//取模(或取余):%
System.out.println(m1 % n1);//输出2
//开发中,经常用来判断某个数num1能整除另外一个数num2。num1 % num2 == 0
//比如:判断num1是否是偶数:num1 % 2 == 0
//结论:取模以后,结果与被模数的符号相同
int m2 = 12;
int n2 = 5;
System.out.println(m2 % n2);//输出2
int m3 = -12;
int n3 = 5;
System.out.println(m3 % n3);//输出-2
int m4 = 12;
int n4 = -5;
System.out.println(m4 % n4);//输出2
int m5 = -12;
int n5 = -5;
System.out.println(m5 % n5);//输出-2
//********************************
//(前)++ :先自增1,后运算
//(后)++ :先运算,后自增1
int a1 = 10;
int b1 = ++a1;
System.out.println("a1 = " + a1 + ",b1 = " + b1); //输出a1 = 11,b1 = 11
int a2 = 10;
int b2= a2++;
System.out.println("a2 = " + a2 + ",b2 = " + b2); //输出a2 = 11,b2 = 10
//练习1:
int i = 10;
//i++;
++i;//这两种方法相同
System.out.println("i = " + i); //输出i = 11
//练习2:
short s1 = 10;
//方式1:
//s1 = s1 + 1;
s1 = (short)(s1 + 1);
System.out.println(s1); //输出s1 = 11
//方式2:
s1++;
System.out.println(s1); //输出12
//********************************
//(前)-- :先自减1,在运算
//(后)++ :先运算,再自减1
//结论:++或--运算,不会改变变量的数据类型
//+ :连接符,只使用于String与其他类型的变量间的运算,而且运算的结果也是String类型。
}
}
- 练习1:
随意给出三位数的整数,打印显示它的个位数,十位数,百位数的值。
格式如下:
数字XXX的情况如下:
个位数:
十位数:
百位数:
例如:
数字153的情况如下:
个位数:3
十位数:5
百位数:1
class AriExer{
public static void main(String[] args) {
int num1 = 153;
int ge = num1 % 10;
int shi = num1 /10 % 10;
int bai = num1 /100;
System.out.println("个位数是" + ge);
System.out.println("十位数是" + shi);
System.out.println("百位数是" + bai);
}
}
- 练习2:
class AriExer1{
public static void main(String[] args) {
int hours = 89;
int day = hours / 24;
int hour = hours % 24;
System.out.println("共奋战了" + day + "天零" + hour + "小时");
//额外的练习1:
System.out.println("5+5=" + 5 + 5); //输出5+5=55
System.out.println("5+5=" + (5 + 5)); //输出5+5=10
//额外的练习2:
byte bb1 = 127;
bb1++;
System.out.println("bb1 = " + bb1); //-128
//额外的练习3:
int i = 1;
int j = i++;
System.out.println(j); //i-->1,i-->j,i-->2,最后输出1
//额外的练习3:
int m = 1;
m= m++;
System.out.println(m); //m-->1,m-->m,m-->2,m-->1最后输出1
}
}
1.8.2 赋值运算符
- = += -= *= \= %=
- 说明:
①当"-"两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。
②支持连续赋值。
③+= -= *= \= %= 操作,不会改变变量本身的数据类型。
class SetValTest{
public static void main(String[] args) {
//******************************
int i = 5;
long l = 1;//自动类型转换
byte b = (byte)i;//强制类型转换
//操作方式1:
int a1 = 10;
int b1 = 10;
//操作方式2:
int a2;
int b2;
//或合并: int a2,b2; //也是可以通过的
a2 = b2 = 10;
System.out.println(a2+","+b2);
//******************************
//说明 += 的使用
int m1 = 10;
m1 += 5;//类似于m1 = m1 + 5;
System.out.println(m1);
byte by1 = 10;
by1 += 5;//by1 = by1 + 5操作会编译报错,因为将int型赋值给byte型。应该写为:by1 = (byte)(by1 + 5);
System.out.println(by1);
int m2 = 1;
m2 *= 0.1;
System.out.println(m2);
//练习1:如何实现变量的值增加2。
//方式1:
int s1 = 10;
s1 = s1 + 2;
//方式2;推荐
int s2 = 10;
s2 += 2;
//练习2:如何实现变量的值增加1。
//方式1:
int c1 = 10;
c1 = c1 + 1;
//方式2:
int c2 = 10;
c1 += 1;
//方式3;推荐
int c3 = 10;
c3++;
//练习3:
int m = 2;
int n = 3;
n *= m++;
System.out.println("m = " + m);//m = 3;
System.out.println("n = " + n);//n= 6;
//练习4:
int n1 = 11;
n1 += (n1++) + (++n1);//n1=11 ---> n1=11 , ---> n1=n12 + (n++11) + (++n12) ---> 常数为25 ---> n1=32
System.out.println(n1);//n1=35
}
}
1.8.3 比较运算符
- == != > < >= <= instanceof
- 说明
① instanceof 在面向对象的多态性的位置讲解。
② == != > < >= <=适用于基本数据类型。(细节: > < >= <= 不适用于boolean类型 ) 运算的结果为boolean类型。
③ 了解:== !=可以适用于引用数据类型
④ 区分: == 与 = 的区别
class CompareTest{
public static void main(String[] args) {
int m1 = 10;
int m2 = 20;
boolean compare1 = m1 > m2;
System.out.println(compare1); //输出false
int n1 = 10;
int n2 = 20;
System.out.println(n1 == n2);//输出false
System.out.println(n1 = n2);//20
boolean b1 = false;
boolean b2 = true;
System.out.println(b1 == b2);//输出false
System.out.println(b1 = b2);//输出true
}
}
- 练习:
- 要求:
今天是周2,10天以后是周几?
要求:控制台输出"今天是周2,10天以后是周X"。
class ConditionExer{
public static void main(String[] args) {
int week = 2;
week = 4;
week += 10;
week %= 7;
System.out.println("今天是周2,10天以后是周" + ((week == 0)? "天" : week));//因为(week == 0)? "天" : week不用输出值,所以字符串和整形类型不一致也没关系。
}
}
1.8.4 逻辑运算符
- & && | || ! ^
- 说明:
① 逻辑运算符针对boolean类型的变量进行的操作。
② 逻辑运算符运算的结果也是boolean类型。
③ 逻辑运算符常使用条件判断结构、循环结构中
class LogicTest{
public static void main(String[] args) {
/*
//***********************************
区分:&(逻辑与)和&&(短路与)
1、相同点:两个符号表达的都是"且"的关系。只有当符号左右两边的类型值均为true时,结果才为true。
2、执行过程:
1)如果符号左边是true,则& 、&& 都会执行符号右边的操作
2)如果符号左边是false,则& 会执行符号右边的操作
&& 不会执行符号右边的操作
3、开发中,推荐使用&&
*/
//比较&时
boolean b1 = false;
int num1 = 10;
if(b1 & (num1++ > 0)){
System.out.println("窗前明月光");
}else{
System.out.println("我是郭德纲");//打印
}
System.out.println("num1 =" + num1);//输出11
//比较&&时
boolean b2 = false;
int num2 = 10;
if(b2 && (num2++ > 0)){
System.out.println("窗前明月光");
}else{
System.out.println("我是郭德纲");//打印
}
System.out.println("num2 =" + num2);//输出10
//***************************************
//***************************************
//比较&时
boolean b3 = false;
b3 = true;
int num3 = 10;
if(b3 & (num3++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num3 =" + num3);//输出11
//比较&&时
boolean b4 = false;
b4 = true;
int num4 = 10;
if(b4 && (num4++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num4 =" + num4);//输出11
/*
//***********************************
区分:|(逻辑或)和||(短路或)
1、相同点:两个符号表达的都是"或"的关系。只有当符号左右两边的类型值均为false时,结果才为false。
2、执行过程:
1)如果符号左边是false,则| 、|| 都会执行符号右边的操作
2)如果符号左边是true, 则| 会执行符号右边的操作
|| 不会执行符号右边的操作
3、开发中,推荐使用||
*/
//比较|时
boolean b5 = false;
int num5 = 10;
if(b5 | (num5++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num5 =" + num5);//输出11
//比较||时
boolean b6 = false;
int num6 = 10;
if(b6 || (num6++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num6 =" + num6);//输出11
//***************************************
//***************************************
//比较|时
boolean b7 = false;
b7 = true;
int num7 = 10;
if(b7 | (num7++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num7 =" + num7);//输出11
//比较||时
boolean b8 = false;
b8 = true;
int num8 = 10;
if(b8 || (num8++ > 0)){
System.out.println("窗前明月光");//打印
}else{
System.out.println("我是郭德纲");
}
System.out.println("num8 =" + num8);//输出10
}
}
通过以上例子:区分两个点
区分:&(逻辑与)和&&(短路与)
1、相同点:两个符号表达的都是"且"的关系。只有当符号左右两边的类型值均为true时,结果才为true。
2、执行过程:
1)如果符号左边是true,则& 、&& 都会执行符号右边的操作
2)如果符号左边是false,则& 会执行符号右边的操作
&& 不会执行符号右边的操作
3、开发中,推荐使用&&
区分:|(逻辑或)和||(短路或)
1、相同点:两个符号表达的都是"或"的关系。只有当符号左右两边的类型值均为false时,结果才为false。
2、执行过程:
1)如果符号左边是false,则| 、|| 都会执行符号右边的操作
2)如果符号左边是true, 则| 会执行符号右边的操作
|| 不会执行符号右边的操作
3、开发中,推荐使用||
- 练习:
- 定义类LogicExer
- 定义main方法
- 定义一个int类型变量a,变量b,都赋值为20
- 定义boolean类型变量bo1,判断++a 是否被3整除,并且a++是否被7整除,将结果赋值给 bo1
- 输出a的值,bo1的值
- 定义boolean类型变量bo2,判断b++ 是否被3整除,并且++b 是否被7整除,将结果赋值给 bo2
- 输出b的值,bo2的值
class LogicExer{
public static void main(String[] args)
{
int a,b;
a = b = 20;
boolean bo1 = (++a % 3 == 0) && (a++ % 7 == 0);
System.out.println("b = " + b + ",bo1 = " + bo1);//b = 20,bo1 = true;
boolean bo2 = (++b % 3 == 0) && (b++ % 7 == 0);
System.out.println("b = " + b + ",bo2 = " + bo2);//b = 22,bo1 = true;
//练习1,区分&& 和 &
int x = 1;
int y = 1;
if(x++ == 2 & ++y == 2){
x = 7;
}
System.out.println("x = " + x + ", y = " + y);//输出x = 2,y = 2
//*******************
int x1 = 1, y1 = 1;
if (x1++ == 2 && ++y1 == 2){
x1 = 7;
}
System.out.println("x1 = " + x1 + ", y1 = " + y1); //输出x1 = 2,y1 = 1
//练习2,区分|| 和 |
int x2 = 1;
int y2 = 1;
if(x2++ == 1 | ++y2 == 1){
x2 = 7;
}
System.out.println("x2 = " + x2 + ", y2 = " + y2);//输出x2 = 7,y2 = 2
//*******************
int x3 = 1, y3 = 1;
if (x3++ == 1 || ++y3 == 1){
x3 = 7;
}
System.out.println("x3 = " + x3 + ", y3 = " + y3); //输出x3 = 7,y3 = 1
//练习3
boolean x4 = true;
boolean y4 = false;
short z4 = 42;
if ((z4++ == 42) && (y4 = true)){
z4++;
}
if ((x4 = false) || (++z4 == 45)){
z4++;
}
System.out.println("z4 = " + z4); //输出z = 46
}
}
1.8.5 位运算符(了解)
- 1. << >> >>> & | ^ ~
- 2.
① << >> >>> & | ^ ~ :针对数值类型的变量或常量进行运算,运算的结果也是数值
②
<<:在一定范围内,每向左移动一位,结果就在原有的基础上*2。(对于正数、负数都适用)
>>:在一定范围内,每向右移动一位,结果就在原有的基础上/2,如果不能整除,向下取整。(对于正数、负数都适用)
- 3.面试题:如何高效的方式计算2*8?
2 << 3 或 8 << 1
class BitTest{
public static void main(String[] args) {
//******************************
//<<
int num1 = 7;
System.out.println("num1 << 1 :" + (num1 << 1));//输出14
System.out.println("num1 << 2 :" + (num1 << 2));//输出28
System.out.println("num1 << 3 :" + (num1 << 3));//输出56
System.out.println("num1 << 28 :" + (num1 << 28));//输出是正数
System.out.println("num1 << 29 :" + (num1 << 29));//输出是负数,过犹不及,所以是在一定范围内的左移
int num2 = -7;
System.out.println("num2 << 1 :" + (num2 << 1));//输出-14
System.out.println("num2 << 2 :" + (num2 << 2));//输出-28
System.out.println("num2 << 3 :" + (num2 << 3));//输出-56
//******************************
//>>
int num3 = 69;
System.out.println("num3 >> 1 :" + (num3 >> 4));//输出4
/*
69的二进制: 0000 0000 0000 0000 0000 0000 0100 0101
69 >> 4:(补0) 0000 0000 0000 0000 0000 0000 0000 0100 (右边移出去四位)0101 ,69 >> 4类似于69/2^4 = 69/16=4
*/
int num4 = -69;
System.out.println("num4 >> 1 :" + (num4 >> 4));//输出-5
/*
-69的二进制:
原码: 1000 0000 0000 0000 0000 0000 0100 0101
反码: 1111 1111 1111 1111 1111 1111 1011 1010
补码: 1111 1111 1111 1111 1111 1111 1011 1011
-69 >> 4:(补1) 1111 1111 1111 1111 1111 1111 1111 1011 (右边移走了四位)
反码: 1111 1111 1111 1111 1111 1111 1111 1010
原码: 1000 0000 0000 0000 0000 0000 0000 0101 (-5) -69 >> 4类似于-69/2^4 = -69/16=-5
*/
//******************************
//>>>,往右移动后,左边空出来的位直接补0。(正数、负数都适用)
int num5 = 69;
System.out.println("num5 >>> 1 :" + (num5 >> 4));//输出4
/*
69的二进制: 0000 0000 0000 0000 0000 0000 0100 0101
69 >> 4:(补0) 0000 0000 0000 0000 0000 0000 0000 0100 (右边移出去四位)0101 ,69 >> 4类似于69/2^4 = 69/16=4
*/
int num6 = -69;
System.out.println("num6 >> 1 :" + (num6 >> 4));//输出-5
/*
-69的二进制:
原码: 1000 0000 0000 0000 0000 0000 0100 0101
反码: 1111 1111 1111 1111 1111 1111 1011 1010
补码: 1111 1111 1111 1111 1111 1111 1011 1011
-69 >> 4:(补0) 0000 1111 1111 1111 1111 1111 1111 1011 (右边移走了四位)
反码: 0000 1111 1111 1111 1111 1111 1111 1011
原码: 0000 1111 1111 1111 1111 1111 1111 1011
最高位是0,是正数,那么原码,反码,补码都一样
*/
//******************************
//&
System.out.println(9 & 7);//输出1
/*
& 是 且的意思,只有两者都为1,&的结果才为1
9的二进制:0000 0000 0000 0000 0000 0000 0000 1001
7的二进制:0000 0000 0000 0000 0000 0000 0000 0111
9 & 7: 0000 0000 0000 0000 0000 0000 0000 0001 (输出1)
*/
System.out.println(-9 & 7);//输出7
/*
-9的二进制:
原码: 1000 0000 0000 0000 0000 0000 0000 1001
反码: 1111 1111 1111 1111 1111 1111 1111 0110
补码: 1111 1111 1111 1111 1111 1111 1111 0111
7的二进制: 0000 0000 0000 0000 0000 0000 0000 0111
-9 & 7: 0000 0000 0000 0000 0000 0000 0000 0111 (输出7)
补码: 0000 0000 0000 0000 0000 0000 0000 0111
反码: 0000 0000 0000 0000 0000 0000 0000 0111
原码: 0000 0000 0000 0000 0000 0000 0000 0111
*/
//******************************
//|
System.out.println(9 | 7);//输出15
/*
| 是 或的意思,只要有1个为1,|的结果就为1
9的二进制:0000 0000 0000 0000 0000 0000 0000 1001
7的二进制:0000 0000 0000 0000 0000 0000 0000 0111
9 & 7: 0000 0000 0000 0000 0000 0000 0000 1111 (输出15)
*/
System.out.println(-9 | 7);//输出-9
/*
| 是 或的意思,只要有1个为1,|的结果就为1
-9的二进制:
原码: 1000 0000 0000 0000 0000 0000 0000 1001
反码: 1111 1111 1111 1111 1111 1111 1111 0110
补码: 1111 1111 1111 1111 1111 1111 1111 0111
7的二进制: 0000 0000 0000 0000 0000 0000 0000 0111
-9 | 7:(补码) 1111 1111 1111 1111 1111 1111 1111 0111 (输出15)
(反码) 1111 1111 1111 1111 1111 1111 1111 0110
(原码) 1000 0000 0000 0000 0000 0000 0000 1001 (输出-9)
*/
//******************************
//^
/*
0^1结果为1
1^1结果为1
1^1结果为0
0^0结果为0
*/
System.out.println(9 ^ 7);//输出14
/*
9的二进制:0000 0000 0000 0000 0000 0000 0000 1001
7的二进制:0000 0000 0000 0000 0000 0000 0000 0111
9 & 7: 0000 0000 0000 0000 0000 0000 0000 1110 (输出14)
*/
System.out.println(-9 | 7);//输出-9
/*
-9的二进制:
原码: 1000 0000 0000 0000 0000 0000 0000 1001
反码: 1111 1111 1111 1111 1111 1111 1111 0110
补码: 1111 1111 1111 1111 1111 1111 1111 0111
7的二进制: 0000 0000 0000 0000 0000 0000 0000 0111
-9 | 7:(补码) 1111 1111 1111 1111 1111 1111 1111 0111
(反码) 1111 1111 1111 1111 1111 1111 1111 0110
(原码) 1000 0000 0000 0000 0000 0000 0000 1001 (输出-9)
*/
//******************************
//~
/*
0~结果为1
1~结果为0
*/
System.out.println(~9);//输出-10
/*
9的二进制: 0000 0000 0000 0000 0000 0000 0000 1001
~9的二进制:
补码:1111 1111 1111 1111 1111 1111 1111 0110
反码:1111 1111 1111 1111 1111 1111 1111 0101
原码:0000 0000 0000 0000 0000 0000 0000 1010 (输出-10)
*/
System.out.println(~(-9));//输出8
/*
-9的二进制:
原码: 1000 0000 0000 0000 0000 0000 0000 1001
反码: 1111 1111 1111 1111 1111 1111 1111 0110
补码: 1111 1111 1111 1111 1111 1111 1111 0111
7的二进制: 0000 0000 0000 0000 0000 0000 0000 1000 (输出8)
*/
System.out.println("~9 :" + ~9);//输出-10
System.out.println("~(-10) :" + ~(-10));//输出9
}
}
- 练习:
- 案例2:如何交换两个int型变量的值?String呢?
class BitExer{
public static void main(String[] args) {
//方法1:声明一个临时变量。(推荐)
int m = 10;
int n = 20;
System.out.println("m = " + m + ",n = " + n);
int temp = m;
m = n;
n = temp;
System.out.println("m = " + m + ",n = " + n);
//方法2:优点:不需要定义临时变量。缺点:难、适用性差(不适用于非数值类型、可能超出int范围)
m = m + n; //m = 30 = 10 + 20
n = m - n; //n = 10 = 30 - 20
m = m - n; //m= 20 = 30 - 10
//方法3:优点:不需要定义临时变量。缺点:真难、适用性差(不适用于非数值类型)
m = m ^ n;
n = m ^ n; //(m ^ n) ^ n ----> m
m = m ^ n;
System.out.println("m = " + m + ",n = " + n);
}
}
1.8.6 条件运算符
- 知识点
1.(条件表达式)? 表达式1 : 表达式2
2.说明:
① 条件表达式的结果是boolean类型。
② 如果条件表达式的结果是true,则执行表达式1。否则,执行表达式2。
③ 表达式1 和 表达式2 需要是相同的类型或能兼容的类型。
④ 开发中,凡是可以使用条件运算符的位置,都可以改写为if-else。
反之,能使用if-else结构,不一定能改写为条件运算符。
建议,在二者都能使用的情况下,推荐使用条件运算符。因为执行率稍高
- 代码:
class ConditionTest{
public static void main(String[] args){
String info = (2 > 1)? "表达式1" : "表达式2";
System.out.println(info);
double result = (3 > 4)? 1 : 2.0;
System.out.println(result);
//练习1:获取两个整数的较大值
int m = 30;
int n = 12;
int max = (m > n)? m : n;
System.out.println("较大值为:" + max);
//练习2:获取三个整数的最大值
int i = 20;
int j = 10;
int k = 34;
int tempMax = (i > j)? i : j;
int finalMax = (tempMax > k)? tempMax : k;
System.out.println(finalMax);
//合并以后的写法:不推荐
int finalMax1 = (((i > j)? i : j) > k)? ((i > j)? i : j) : k;
System.out.println(finalMax1);
}
}
- 练习:
-
今天是周2,10天以后是周几?
要求:控制台输出"今天是周2,10天以后是周X"。
class ConditionExer{
public static void main(String[] args) {
int week = 2;
week = 4;
week += 10;
week %= 7;
System.out.println("今天是周2,10天以后是周" + ((week == 0)? "天" : week));//因为(week == 0)? "天" : week不用输出值,所以字符串和整形类型不一致也没关系。
}
}
1.8.7运算符的优先级
- 如果想体现优先级比较高,使用()
- 我们在编写一执行语句时,不要出现太多的运算符。
二、企业真题
1.高效的方式计算2*8的值。
使用2 << 3 或者 8 << 1
2.& 和 &&的区别?
既有相同点,又有不同点,在false时体现。
3.java中的基本类型有哪些?String是最基本的数据类型吗?
8种数据类型。
String不是,属于引用数据类型。
4.java中的基本数据类型包括那些?(同3)
5.java开发中计算金额时使用什么数据类型?
不能使用float或double,因为精度不高。
使用BigDecimal类替换,可以实现任意精度的数据的运算。
6.char型变量中能不能存储一个中文汉字,为什么?
可以的。
char c1 = '中';
char c2 = 'a';
因为char使用的是unicode字符集,包含了世界范围的所有的字符。
7.代码分析
short s1 = 1;
s1 = s1 + 1; //错在右边是int型,s1是short型,需要强制转换
short s1 = 1;
s1 += 1; //没有错
8.int i = 0; i = i++ 执行这两句话后变量i的值为
0。因为是(后)++,先运算,后赋值。
9.如何将两个变量的值互换
String s1 = "abc";
String s2 = "123";
String temp = s1;
s1 = s2;
s2 = temp;
10.boolean占几个字节
编译不谈占几个字节
但是JVM在给boolean类型分配内存空间时,boolean类型的变量占据一个槽位(slot,等于4个字节)。
细节:true:1 false:0
>扩展:在内存中,byte\short\char\boolean\int\float :占用1个slot
double\long :占用2个slot
11.为什么java中0.1+0.2结果不是0.3?
在代码中测试0.1+0.2,你会惊讶的发现,结果不是0.3,而是0.3000......4。这是为什么?
几乎所有现代的编程语言都会遇到上述问题,包括JavaScript、Ruby、Python、Swift和Go等。引发这个问题的原因是,它们都采用了IEEE 754标准。
IEEE是指"电子与电子工程师协会",其在1985年发布了一个IEEE 754计算标准,根据这个标准,小数的二进制表达能够有最大的精度上限提升。但无论如何,物理边界是突破不了的,它仍然不能实现 "每一个十进制小数,都对应一个二进制小数" 。正因如此,产生了0.1+0.2不等于0.3的问题。
具体的:
整数变为二进制,能够做到"每一个十进制小数,都对应一个二进制小数",比如数字3,二进制就是11;再比如数字43就是二进制101011,这个毫无争议。
对于小数,并不能做到"每一个十进制小数,都对应一个二进制小数"。举例来说,二进制小数0.0001表示十进制数0.0625(至于它是如何计算的,不用深究);二进制小数0.0010表示十进制数0.125;二进制小数0.0011表示十进制数0.1875。看,对于四位的二进制小数,二进制小数虽然是连贯的,但是十进制小数却不是连贯的。比如,你无法用四位二进制小数的形式表示0.125~0.1875之间的十进制小数。
所以在编程中,遇见小数判断相等情况,比如开发银行、交易等系统,可以采用"四舍五入"或者"同乘同除"等方式进行验证,避免上述问题。