2.1 标识符与关键字
2.1.1 标识符
对于变量、常量、函数、方法名等等的命名统一称为标识符,Java对于标识符的要求有:
1、数字、字母、下划线、$组成,数字不能作为标识符的开头,标识符也不能与关键字和保留字重名;
2、命名时尽可能简单、有意义;
3、”$”(用双引号引起来的$)尽量不要在代码中出现。
4、一个推荐的命名规范:
1)代码中的命名均不能以下划线或美元符号开始,也不能以下划线和美元符号结束。
2)代码命名严禁使用拼音与英文混合的方式,更不允许直接使用中文。
3)类名使用UpperCamelCase风格,方法名、参数名、成员变量、局部变量统一使用lowerCamelCase风格。
4)常量命名全部大写,单词间用下划线隔开。
5、大驼峰(UpperCamelCase)和小驼峰(lowerCamelCase):
对于类名,类名是以大写字母开头的名词;如果类名由多个单词组成,则每个单词的首字母大写。eg:FirstSample。并且,源文件的文件名必须与公共类的名字相同。
对于变量,如果只含有一个单词,则全部小写;如果变量名由多个单词组成,则从第二个单词开始,每个单词的首字母大写。
2.1.2 关键字
Java中的关键字有:
权限控制 | private | protected | public |
|
|
定义修饰 | abstract | final | synchronized |
|
|
类间关系 | extends | implements |
|
|
|
实例相关 | new | this | super | instanceof |
|
异常处理 | try | catch | finally | throw | throws |
包相关 | package | import |
|
|
|
其他 | native | strictfp | transient | volatile | assert |
说明:1、java中有两个未使用的保留字:goto、const,这两个保留字没有含义,但不保证未来的Java版本加入对这两个保留字的支持。 2、null、ture、false这三个词有特殊含义,不要随意使用 3、assert(1.4之后添加)、enum(1.5之后添加) |
2.2数据类型
Java中的数据类型分为基本数据类型(值类型)和引用数据类型。
2.2.1 基本数据类型
1、基本数据分类
基本数据类型分为三类:数值型、字符型、布尔型。
分类 | 数据类型 | 存储字长 | 默认值 | 数据范围 |
数值型 | byte | 1字节 | 0 | -128~+127 |
short | 2字节 | 0 | -32768~+32767 | |
int | 4字节 | 0 | -2^31~2^31-1 | |
long | 8字节 | 0l | -2^63~2^63-1 | |
double | 8字节 | 0.0d | IEEE 64位标准浮点数范围(双精度) | |
float | 4字节 | 0.0f | IEEE 32位标准浮点数范围(单精度) | |
字符型 | char | 2字节 | \u0000 | 0~65535 |
布尔型 | Boolean | 1 bit | false | true/false |
备注:整型的立即数如果不强调类型,默认为int型 浮点型的立即数如果不强调类型,默认为double型。 布尔类型只承认false和true,不支持0为假1为真这种操作 |
2、基本数据类型的强制类型转换
下图表示数据类型自动转换,其中黑色表示自动转换时不会造成数据丢失,红色则可能会出现数据丢失问题。但是其他方向的数据类型转换要做强制类型转换(类型),此外还肯能会存在精度损失的问题。boolean类型不能参与数据类型转换。
2.2.2 引用数据类型
在java中,引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明是被指定为一个特定的类型。变量一旦声明后类型就不能改变了。例如数组、对象、字符串(String)等都是引用数据类型,默认值都是null。一个引用变量可以用来与任何与之兼容的类型。
2.2.3 值类型与引用类型的区别
1、传递方式不同:基本数据类型的赋值操作是值传递,当值类型变量a赋值给值类型变量b之后,再去改变a的值那么b不会随着a的改变而改变。而引用数据类型的赋值是引用传递,也就是说当a赋值给变量b之后,两个变量中任何一个数据改变都会引发另一个变量发生相应的变化。
2、内存分配方式不同:值类型的数据会直接存储在栈中,Java的JVM会直接在内存中开辟出一块区域来存储这些数据;而对于引用数据类型,Java的JVM会将数据存储在堆中,在栈上开辟一块空间用于存储指向这个堆的地址,栈中的地址来引用堆的数据;此外,当堆中的数据没有被任何一个栈所指向,那么这个堆空间就被视为垃圾内存,会被Java虚拟机回收。
例题:下面有关值类型和引用类型描述正确的是(A)? |
A.值类型的变量赋值只是进行数据复制,创建一个同值的新对象,而引用类型变量赋值,仅仅是把对象的引用的指针赋值给变量,使它们共用一个内存地址。 |
B.值类型数据是在栈上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。而引用类型数据是分配在堆上,引用类型的变量通常包含一个指向实例的指针,变量通过指针来引用实例。 |
C.引用类型一般都具有继承性,但是值类型一般都是封装的,因此值类型不能作为其他任何类型的基类。 |
D.值类型变量的作用域主要是在栈上分配内存空间内,而引用类型变量作用域主要在分配的堆上。 |
2.3 运算符
算术运算符 | + | - | * | / | % | ++ | -- |
加 | 减 | 乘 | 除 | 取余 | 自增 | 自减 | |
关系运算符 | == | != | > | >= | < | <= |
|
相等 | 不等 | 大于 | 大于等于 | 小于 | 小于等于 |
| |
位运算符 | & | | | ^ | ~ | >> | << |
|
按位与 | 按位或 | 按位异或 | 按位取反 | 右移 | 左移 |
| |
逻辑运算符 | && | || | ! |
|
|
|
|
逻辑与 | 逻辑或 | 逻辑非 |
|
|
|
| |
赋值运算符 | = |
|
|
|
|
|
|
赋值运算 |
|
|
|
|
|
| |
其他运算符 | A?B:C | instanceof |
|
|
|
|
|
条件运算 | 类属关系 |
|
|
|
|
|
2.4 分支结构
分支结构:进行逻辑判断,当满足某些条件时才会执行对应的语句。
2.4.1 if
表达方式(两种方式均可)
if(布尔表达式){ //条件满足时执行代码 }else{ //条件不满足时执行代码 } | if(布尔表达式){ //条件满足时执行代码 }else if(布尔表达式){ //条件满足时执行代码 } ... else{ //条件都不满足时执行代码 } |
if语句可以实现对条件的判断,但是如果进行的是多值判断,可以使用switch语句。
2.4.2 switch
表达方式
switch(数字|枚举|字符|字符串){ case 内容1 : { 内容满足时执行语句; [break;] } case 内容2 : { 内容满足时执行语句; [break;] } ... default:{ 内容都不满足时执行语句; [break;] } } |
一旦switch找到对应的case后,这个case后所有的语句都要执行直到出现break语句或者达到switch结构的结尾。
2.5 循环结构
循环结构:在满足一定的条件下可以重复执行指定的某几行代码,这个条件可以在一定情况下不满足。
2.5.1 while/do……while
表达方式
while | do……while |
while(循环结束条件判断){ 循环语句; 修改修改循环结束判断; } | do{ 循环语句; 修改循环结束判断; }while(循环结束条件判断); |
while与do……while的区别:do……while语句无论条件是否满足,循环体至少都要执行一次,而while语句如果条件不成立,一次也不执行。
2.5.2 for
表达方式
for(循环初始化;循环结束判断;修改循环结束条件){ 循环体; } |
例:以下程序执行后输出结果是 (C) 。
public class Test { } |
(A) first-second-others-second-others-others-others
(B) first-second-others- others-
(C) first-second- second- others-others-
(D) first-second- second-others-
2.5.3 循环控制(continue/break)
continue:执行到此语句时会跳过当前循环的剩余部分,返回循环判断。而对于for循环,将跳转到修改循环结束条件,执行后在进行判断。
break:退出整个循环
2.6 方法
方法是一段可以被重复调用的代码块,类似于C语言中函数的概念。
2.6.1方法的声明
public static 方法返回值 方法名称([参数类型 变量 ...]){ 方法体代码; [return 返回值]; } |
方法返回值:与return配合使用,将方法的结果返回到上一级方法。方法返回值类型可以为基本类型和引用类型。返回类型也可以是空(void),而return语句可以用来结束调用。
2.6.2 方法重载
定义:方法名称相同,参数列表不同(参数的类型、顺序或者个数不同),方法名称和参数列表合起来成为方法签名。(返回类型不是签名的一部分)。
注意:不能有名字相同,参数类型相同但返回类型不同的两个方法。
方法重载的例子:
public static int add(int x,int y){ return x+y; } public static int add(int x,int y,int z){ return x+y+z; }//方法重载,实现了用同一个方法名分别完成两数相加或者三数相加的方法 |
2.6.3 方法递归
方法递归简称就是:我用我自己。指的是一个方法自己调用自己的方式。这种调用必须要有调用结束的条件,此外在每次调用方法时,判断递归继续的条件要有一定的变更。
例如,使用递归方法完成1到100的求和:
public class Test{ public static void main(String[] args) { System.out.println(sum(100)); } public static int sum(int num){ if (num == 1) { return 1; }else { return num+sum(num-1); } } } |
需要说明的是,使用while循环的操作,大部分都可以使用递归替换,用于简化代码结构,阅读起来也更加直观。
2.7 数组
数组指的就是一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作。在Java中数组属于引用数据类型,在使用之前一定要实例化(开辟空间),否则会产生空指针中断。
2.7.1. 数组基本概念
声明并开辟数组: | 数据类型[] 数组名称 = new 数据类型 [长度] ; |
数组的访问: | 数据类型[索引],索引从0开始到(长度-1),一旦访问越界就会出现数组越界异常 |
| 利用for循环实现依次访问 |
| 访问数组长度:数组名.length |
注意: | 数组的数据类型可以是基本数据类型也可以是引用数据类型 |
下面是两个例子
public class ArrayDemo{ public static void main(String[] args) { int[] x = new int[3] ; // 开辟了一个长度为3的数组 System.out.println(x.length) ; x[0] = 1 ; // 数组第一个元素 x[1] = 2 ; // 数组第二个元素 x[2] = 3 ; // 数组第三个元素 for (int i = 0; i<x.length ; i++) { System.out.println(x[i]) ; // 通过循环控制索引下标更改 } } |
public class ArrayDemo{ public static void main(String[] args) { int[] x = null ; int[] temp = null ; // 声明对象 x = new int[3] ; System.out.println(x.length) ; x[0] = 1 ; // 数组第一个元素 x[1] = 2 ; // 数组第二个元素 x[2] = 3 ; // 数组第三个元素 for (int i = 0; i<x.length ; i++) { System.out.println(x[i]) ; // 通过循环控制索引下标更改 } temp = x ; //如果要发生引用传递,不要出现[] temp[0] = 55 ; // 修改数据 System.out.println(x[0]) ; } } |
class Person { private String name ; private int age ; public Person(String name, int age) { this.name = name ; this.age = age ; } public void getInfo() { System.out.println("姓名:"+this.name+",年龄:"+this.age) ; }
} public class Test { public static void main(String[] args){ Person[] per = new Person[] { new Person("张三",1) , new Person("李四",2) , new Person("王五",3) } ; // 对象数组静态初始化 for (int x = 0 ; x < per.length ; x++) { per[x].getInfo() ; } } } |
Java数组在内存中的保存方式:
Java将内存区域分为栈内存和堆内存两块区域(实际上比这个分类复杂,之后在JVM会详细说明)
栈内存(虚拟机局部变量表):存放的是局部变量(包含编译期可知的各种基本数据类型、对象引用-即堆内存的地址,可以简单的理解为对象的名称),Java栈是与线程对应起来的,每当创建一个线程,JVM就会为这个线程创建一个对应的Java栈。
堆内存:保存的是真正的数据。即对象的属性信息
声明一个数组时,首先会在内存的栈上开辟一个栈内存,用于表明数组,当这个数组进行实例化时,实例化的对象内容会被放在堆内存中,并且栈内存的指针会指向堆内存的这块内存。
一旦发生引用传递(本质上是一块堆内存可以被多个栈内存所指向),那么这两个栈内存都会指向同一个堆内存,那么之后一旦对其中一个数组的某个元素发生修改,这两个数组的对应元素都会发生修改。例如下面的代码:
int[] data = new int[2]{1,2}; int[] temp = null; temp = data; |
2.7.2. 二维数组(了解)
二维数组在实际的编程中不常使用,仅做了解。为了方便理解,除非特殊说明,之后提到的数组默认为一维数组。
声明并开辟数组: | 数据类型[][] 对象数组 = new 数据类型[行个数][列个数] ; |
数组的访问: | 利用两层for循环实现对数组内元素依次访问 |
int[][] data = new int[][] { {1,2,3},{4,5},{6,7,8,9} }; for (int x = 0; x<data.length ; x++) { for (int y = 0; y<data[x].length ; y ++) { System.out.println("data{"+x+"]["+y+"]="+data[x][y]+"、") ; }// 在进行输出的时候一定要使用双重循环 System.out.println(); } |
2.7.3. 数组与方法互操作
由于数组时引用数据类型,这种数据类型可以作为方法的返回值或者方法参数,也可以利用方法调用来修改数组。
当方法接受一个数组参数时,首先会在栈内存中开辟一个内存空间指向堆内存的对应内存空间,那么这样就发生了引用传递。也就是说,一旦这个数组内的元素发生变化,方法执行完毕返回后这个数组的变化是永久的。
2.7.4. Java对数组的支持
Java内置了许多对数组相关的操作,这些操作都封装在方法中,如果需要使用这些方法,则需要引用对应的程序包。