Java基础(一)语法基础

大纲

JAVA基础

1.Java语言及JVM

知识点:

1)什么是Java语言:

  • Java是跨平台的纯面向对象的语言

2)JVM概念:

  • JVM是运行在操作系统之上,是一个可以运行java代码的虚拟计算机;
  • 对于不同的平台,有不同的虚拟机,其屏蔽了底层运行平台的差别,实现了“一次编译,导出运行”。

什么是JDK、JRE、JVM,及其之间的关系:

  • JDK(Java Development Kit,Java开发工具包):
    • 包含JRE以及一些开发工具
    • 面向开发人员使用(开发用的)
    • JDK:javac.exe:编译工具, java.exe:运行工具
  • JRE(Java Runtime Environment,Java运行时环境):
    • 包含JVM以及一些核心的运行类库,面向运行人员使用(运行用的)
    • 核心类库,简单理解就是已经写好的java代码(eg.写代码时System等代码的使用)
  • JVM(Java Virtual Machine, Java 虚拟机):
    • 包含字节码等核心内容(核心所在,跨平台的关键)
    • 运行程序的载体【平台】
      在这里插入图片描述

java编译运行原理

问题:为什么Java能够实现“一次编译,到处运行”?

  • Java 引入了字节码的概念,JVM只能认识字节码,并将它们解释到系统的 API 调用,JVM把字节码解释成具体平台上的机器指令
  • 对于不同的平台,有不同的虚拟机,其屏蔽了底层运行平台的差别,实现了“一次编译,导出运行”。
    在这里插入图片描述

编译运行流程:

在这里插入图片描述

2.数据类型

基础数据类型,四类八种:

1)整数类型:(使用最多的是int)
- byte 1个字节;范围 : -128~127 2^7=128 + 一位符号位
- short 2个字节
- int 4个字节
- long 8个字节
-
2)小数类型:

  • float(单精度) 4个字节
  • double(双精度) 8个字节

3)布尔类型:

  • boolean 1个字节 true false

  • 回答:理论上来说,八分之一个字节就能表示他的大小,但是计算机当中最小的存储单元是字节,所以它应该占1个字节。

boolean类型数据注意事项:

  • 只允许取值true和false,无null
  • 不可以 0 或非 0 的整数替代false和true,这点和C语言不同
  • boolean类型不可以转换为其它的数据类型
  • Java虚拟机中没有任何供boolean值专用的字节码指令,java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:true用1表示,false用0表示《java虚拟机规范 8版》

4)字符类型:

  • char 2个字节 0~65535 = 2^(2*8)-1
// a = 97
// A = 65
// 0 = 48
char c1 = ‘a’;
char c2 = 65;
char c3 = 48;

占用空间/取值范围:

  • 计算机中最小的存储[单元] - 字节-byte
  • 计算机中最小的存储[单位] - 位-Bit-比特
  • 1个字节 = 8个位 (Bit) 比特位

问题:byte存储空间为8,最小值为 1111 1111 不应该代表 -127么?

Java程序默认的运算是十进制, 但是在底层运算的过程中, 都是以二进制(补码)的形式在运算.

byte b = (byte) 130//问 b的值是?
/*
130存储形式:0000 0000 0000 0000 0000 0000 1000 0010
对应byte8位补码的存储为:1000 0010  其反码为  1000 0001  其源码为 1111 1110   
对应十进制为 -126
*/

默认值:

  • 整数(四种类型): 0
  • 小数(两种类型): 0.0
  • 布尔: false
  • 字符: 0 或写为:’\u0000’(表现为空)
  • 引用数据类型: null

注意事项:

1)所有整数默认都是int类型 、所有小数默认都是double

2)定义float类型变量应该加F的标识

float num = 12.3; 
//一开始就会报错,需要加F标识:
float num2 = 12.3F;
//因为12.3常量默认是8个字节的double类型,直接赋值会报错(因为涉及强制转换,应转换为float类型);

3)定义Long类型变量应该加L的标识,建议使用大写.

long num = 12345678; 
//常量值默认是用int类型存储的,当数值过大时会产生溢出,正确做法如下:
long num = 123456789999L;

4)为什么float占4个字节,long占8个字节,float却比long要大呢?

  • 因为整数和小数,底层的二进制存储结构不同.

5)byte, short, char, int 在一起运算的时候, 都会先提升为int (因为所有整数默认都是int类型),

  • 其余类型的运算, 都是小的提升为大的.

3.运算符

知识点:

  • 运算符的分类?

  • 算数运算符有哪些?

      算数运算符(自增自减运算符)
      赋值运算符 
      扩展赋值运算符:+= 、-=、*=、/= 、%=
      关系运算符[比较运算符]
      逻辑运算符
      三元运算符[三目运算符]
    

注意事项:

  • 1)整数相除结果只能是整数
  • 2)如果想计算出小数, 必须要有浮点类型数据参数运算
  • 3)字符与字符串参与加法运算
  • 4)自增与自减操作【案例
int x = 4;
//   4 +  6 + 60
int y = (x++)+(++x)+(x*10);

System.out.println("x="+x);        // x=6
System.out.println("y="+y);        // y=70

System.out.println("---------------");
  • 5)=和==要区分明白
    =:赋值的
    ==:比较的

  • 6)与、或、 非 以及 短路与、短路或、异或

    && : 从最终结果来看,跟&的效果是一样的,也是与false则false,但是&&具有短路效果,运行效果会提升(但要注意短路产生的影响)

    || : 遇true则true,也具备短路效果,当左边为true,右边就不执行了。

    ^(异或) :

    • 现象: 相同为false,不同为true(处对象)
    • 特点:一个数,被另外一个数,异或两次,该数本身不变。

    因为在每一位上:

    • 1)0位:不管0遇到谁(0或1),异或后其值都会与该值相同(0或1),此时再与该值(0或1)异或,对应位的值相同,结果都为0;
    • 2)1位:不管1遇到谁(0或1),异或后其值都会与该值相反(1或0),此时再与该值(0或1)异或,对应位的值相反,结果都为1;

面试题:实现两个变量的数值交换, 不允许定义三方变量

public static void main(String[] args) {
        int a = 10;
        int b = 20;

        a = a ^ b;        // 10 ^ 20
        b = a ^ b;        // 10 ^ 20 ^ 20        --> 10
        a = a ^ b;        // 10 ^ 20 ^ 10     --> 20

        System.out.println(a);
        System.out.println(b);
    }
  • 7)三元运算符

格式: (比较表达式) ? 值1 :值 2

注意事项:

  • 三元运算符的结果,必须被使用(如赋给变量、输出……)

      hold?fish:palm;
    
  • 8)位运算符
    >> 右移 二进制进行右移 最高位是0,则空缺位用0补齐,最高位是1,则空缺位用1补齐
    >>> 无符号右移 最高位用0补齐
    << 高位舍弃,空缺位用0补齐

赋值运算中的类型转换

- 隐式/显式转换:将大的数据类型,给小的数据类型赋值,不能直接赋值,需要强转符号
- 底层强制转换 += 、 -=  ......
- 常量优化机制
// 案例一:隐式/显式转换  会报错
short s=1;    
s=s+1; // s是short类型,1是int类型,short和int相加的时候,会先将short提升为int
		// 两个int相加的结果,还是int,把int结果赋值给short类型的变量,需要强转。       

System.out.println("---------------");   

// 案例二:底层强制转换 不会 报错
short s=1;
s+=1;     //原因:底层自动做了强制类型转换        其等价于 —>    
// s = (short)(s+1);   

----------------------
// 案例三:
byte b1=3,b2=4,b;
b=b1+b2;

1. 因为所有整数默认都是int类型,b1和b2两个byte类型在做运算之前,会先各自提升为int类型,然后再做运算
 两个变量都提升为int类型了,两个int相加,结果还是int,将int数据赋值给byte,不能直接赋值,应该加入强转。

2. 因为b1和b2是两个变量,变量内部所记录的值是不可控的,有可能相加之后的结果就超出了byte的取值范围		
----------------------
常量优化机制
----------------------		
b=3+4;
因为34是两个常量,Java有常量优化机制,在编译的时候就会将34进行相加,然后看相加的结果是否在byte的取值范围。

4.流程控制

知识点

流程控制语句的分类:

  • 顺序结构
  • 选择结构:
    • if
    • switch
  • 循环结构:
    • for
    • while
    • do … while

if语句

三种格式:

格式1if(比较表达式){  //注意 0、1等常量值不能代表 布尔值
	语句体;
}
//if语句的语句体,如果是一条语句,大括号可以省略不写
if()
	语句体;

格式2if(比较表达式){
	语句体1;
}else{
	语句体2;
}

格式3if(比较表达式1) {
	语句体1;
}else if(比较表达式2) {
	语句体2;
}else if(比较表达式3) {
	语句体3;
}
...
else {
	语句体n+1;
}	

switch语句

switch(将要匹配的值) {
	case1:
		语句体1;
		break;
	case2:
		语句体2;
		break;default:	
		语句体n+1;
		break;
}

注意事项:

  • 1)case后面的值只能是常量, 不能是变量
  • 2)case后面的值不允许重复定义!

问题:

  • 1)break语句可以省略吗?

    • 可以省略,但是不建议,因为会出现case穿透的现象
  • 2)default语句可以省略吗?

    • 可以省略,但是不建议,因为需要default对范围外的错误值,给出提示.
  • 3)表达式(将要匹配的值)可以接受的值为?

    • 基本数据类型:byte short char (int) -> 只要是能够提升为int类型的

    • 引用数据类型:枚举、字符串(jdk1.5之后可以接收枚举,jdk1.7之后可以接收String字符串)

  • 4)swich语言什么时候会停止运行:

    • 当遇到break时;
    • 当不会遇到break时,会按照逻辑一直穿透,直到运行遇到到大括号时;
  • 5)default语句位置没有固定要求,且可以省略;

全部没有breakcase穿透:

public static void main(String[] args) {
	int x = 0;
	int y = 0;
	
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入x值(默认为0):");
	x = sc.nextInt();
	
	switch (x) {
		default:
			y++;		
		case 3:
			y++;		
		case 4:
			y++;		
		case 5:
			y++;		
	}
	
	System.out.println("y值为:" + y);
	// x = 0 -> y = 4;
	//x = 3 -> y = 3;
	//x = 5 -> y = 1;
}

循环语句

1.for循环
for(初始化语句; 循环判断语句; 循环后的步进语句){
	循环体;
}

2.while循环
初始化语句;

while(判断条件语句){
	循环体;
	循环后的步进语句;
}

3.do while循环
初始化语句;
do {
	循环体语句;
	控制条件语句;
}while(判断条件语句);

三种循环的区别?

  1. (for循环while)和do…while的区别 :

    for循环和while循环,都是在判断条件满足的情况下,才会进入循环执行循环体.

    do…while循环, 无论条件是否满足, 都至少执行一次循环体.

  2. for和while的区别:

    for循环内部定义的变量, 在循环结束后, 将会从内存中释放掉
    如果想要在循环结束后, 继续使用控制循环的那个变量, 就可以使用while循环

for each*

break 与 continue

break语句:

  • 1: 用于结束循环, 或者是switch语句
  • 2: break语句只能应用在循环和switch语句当中
  • 3:如果循环嵌套循环,break只能结束自己所在的那一层循环,如果想要结束指定的循环,可以加入标号
public static void main(String[] args) {
	lo:while(true){
		for(int i = 1; i <= 10; i++){
			if(i == 3){
				break lo;
			}
			System.out.println("HelloWorld");
		}
		System.out.println("------------");
	}
}

continue:

  • 1: 终止本次循环, 继续下一次循环 (跳过后继续)
  • 2: 只能在循环当中使用

5.数组

使用过程

1)声明数组

int[] a;

int a[];

Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5];    //非法

2)分配空间

a = new int[5];

3)赋值

a[0] = 5;

4)操作

数组初始化

数组的初始化:给变量开辟内存空间,并为数组中每个元素赋予初始值

动态初始化静态初始化 的区别

  • 动态初始化:只给出长度,由系统给出初始化值 int[] arr = new int[2];

  • 静态初始化:直接通过大括号,给出初始值,由系统决定数组长度 int[] arr = {11, 22, 33};

1)动态初始化

数据类型[] 数组名 = new 数据类型[数组的长度];

int[] arr = new int[3];
// 在内存中开辟了3个连续大小的内存空间, 这三个空间可以存储3个int类型整数

在这里插入图片描述

2)静态初始化

完整格式:

  • 数据类型[ ] 数组名 = new 数据类型[ ]{元素1, 元素2, 元素3…};

简化格式

  • 数据类型[ ] 数组名 = {元素1, 元素2, 元素3…};

int[] arr = {11, 22, 33};

注意:

  • 不能动静结合
  • int[] arr2 = new int[3]{11,22,33}; // 编译错误, 语法错误

其他

1)打印数组变量

打印数组变量的结果:System.out.println(arr);
	
	 * [D@4d687dcd
	 * 
	 * @ : 分隔符
	 * [ : 代表的是数组类型, 几个中括号就代表的是几维数组
	 * D : 代表的是double类型
	 * 
	 * 4d687dcd : 十六进制地址值
	 * 
	 * 十六进制: 1 2 3 4 5 6 7 8 9 a b c d e f 	

问题: 描述下列代码的每一步代表什么
char[] arr = new char[2];		
// 这是创建了一个char类型数组, 变量名叫arr, 数组中可以存储2个char类型字符.

2)数组操作的两个常见小问题

  • 1: ArrayIndexOutOfBoundsException : 数组索引越界异常

    原因: 访问了不存在的索引

  • 2: NullPointerException : 空指针异常

    原因 : 将一个引用数据类型赋值为null之后, 就跟堆内存的引用切断了,这时候再想访问堆内存中的数据, 就会出现空指针异常.

6.方法

定义

修饰符 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2...){
    方法体;
    return 返回值;
} 

修饰符 : 如 public权限修饰符 static状态修饰符

返回值类型 : 跟返回值有关.(若不需要返回值 则使用 void)

方法名 : 合法的标识符即可(自己起的名字)

参数类型 参数名1 (参数列表) : 方法运行所需要参数

方法体 : 方法真正执行的代码逻辑.

return :

  1. 用于结束方法
  2. 用于将返回值携带给调用者
  3. 如果方法的返回值类型是void, return语句可以省略不写

方法调用之方法调用图解

在这里插入图片描述

方法的重载overload

什么是重载:同一类中,方法名相同,参数列表不同,与返回值无关。

参数列表不同包括:

  • 个数不同;
  • 类型不同;
  • 顺序不同(没有意义,但不会报错)

注意事项:

  • 在调用方法的时候,java虚拟机会根据方法名及参数列表的不同来区分方法。

问题1:参数类型为int的方法能否接受byte的数据? (可以,因为含有隐式转换)

public static void main(String[] args) {
    byte b1 = 10;
    byte b2 = 20;
    check(b1,b2);
}

public static boolean check(int a, int b){
    System.out.println("int...");
    return a == b;
}

问题2:有两个方法,参数列表为byte 和 int类型,如果直接调用方法传入两个整数常量, 会匹配到int, 如果非要匹配byte可以加入强制转换.

public static void main(String[] args) {
   check((byte)10,(byte)20);
}

public static boolean check(int a, int b){
   System.out.println("int...");
   return a == b;
}

public static boolean check(byte a, byte b){
   System.out.println("byte...");
   return a == b;
}

问题3: Java当中到底是值传递, 还是址传递?

基本数据类型, 传递的是值, 引用数据类型的时候传递的是地址值.

方法的重写*

7.各类关键字*

权限修饰符

状态修饰符

发布了63 篇原创文章 · 获赞 10 · 访问量 9944

猜你喜欢

转载自blog.csdn.net/select_alter_drop/article/details/104198434