Java基础语法
Java基础语法
注释
- 单句注释 //
- 段落注释 /* */
- 文档注释

标识符
标识符注意点
-
所有的标识符都应该以字母(A-Z或a-z)、美元符($)或者下划线(_)开始
-
首字母之后可以是字母(A-Z或a-z)、美元符($)、下划线(_)或者数字的任意字符组合
-
不能使用关键字作为变量名或方法名
-
标识符是大小写敏感的
-
合法标识符举例:age、$salsry、_value、__1_value
-
非法标识符举例:123abc、-salary、#abc
-
可以使用中文命名,但是一般不建议这样去做
数据类型
强类型语言:要求变量使用要严格符合所有规定,所有变量都必须先定义后才能使用
基本数据类型
数值类型
整数类型
-
byte 占1个字节范围
byte num1 = 10; -
short 占2个字节范围
short num2 = 20; -
int 占4个字节范围
int num3 = 30; -
long 占8个字节范围
long num4 = 30L;
浮点类型
-
float 占4个字节
float num5 = 50.1F; -
double 占8个字节
dounle num6 = 3.1415926;
字符类型
-
char 占2个字节
char name = 'A';
boolean类型(布尔值)
-
占1位其值只有true和false两个
boolean flag = ture; //boolean flag = false;
整数拓展
进制 二进制ob 十进制 八进制0 十六进制0x
int i =10;
int i2 =010;//八进制0
int i3 = 0x10;//十六进制
浮点数拓展
-
float 有限 离散 舍入误差 大约 接近但不等于
-
BigDecimal 数学工具类
![img]()
字符拓展
-
强制转换
![img]()
-
转义字符
布尔值拓展
boolean flag = true;
if (flag==true){}
if (flag){}
类型转换
运算中,不同类型的数据先转化为同一类型,然后进行运算
byte,short,char->int->long->float->double
-
强制类型转换
(类型)变量名 高->低
int i = 128;
byte b = (byte)i;//内存溢出
-
自动变量转换
低->高
int i = 128;
double b = i;
注意点:
- 不能对布尔值进行转换
- 不能把对象类型转换为不相干的类型
- 在把高容量转换到低容量的时候,强制转换
- 转换的时候可能存在内存溢出或者精度问题
操作比较大的时候,注意溢出问题
JDK7新特性,数字之间可以用下划线分割
int money = 10_0000_0000;
变量
变量就是可以变化的量
注意点:
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型
- 变量名必须是合法标识符
- 变量声明是一条完整的语句,因此每一个声明必须以分号结束
类变量 static

常量
初始化后不能再改变的值,不会变动的值
常量名一般使用大写字符
变量的命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:**首字母小写和驼峰原则:moneySalary 除了第一个单词以外,后面的单词首字母大写 **
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run(),runRun()
运算符
- 算数运算符:+,-,*,/,%,++,--
- 赋值运算符=
- 关系运算符:<,>,>=,<=,==,!=instanceof
- 逻辑运算符:&&,||,!
- 位运算符:&,|,^,~,>>,<<,>>>
- 条件运算符?,:
- 扩展赋值运算符:+=,-=,*=,/=

运算数值里有long类型,结果为long类型,如果没有,结果则为int
同理,如果里面有double类型,则结果为double类型
关系运算符通过布尔值体现

很多运算会使用工具类来做

逻辑运算

短路运算
boolean a = true;
boolean b = false;
System.out.println(a && b);//true
System.out.println(b && a);//false
//&&第一个为真,则运算结果为真,第一个为假,则运算结果为假
位运算
/*
A = 0011 1100
B = 0000 1101
A&B = 0000 1100 上下相乘
A|B = 0011 1101 如果上下都是0,则为0,有一个1则为1
A^B = 0011 0001 相同则为0,不同则为1
~B = 1111 0010 与B完全相反
2*8 = 16
<< 左移 相当于*2
>> 右移 相当于/2
2<<3
*/
字符串连接符

""+a+b //字符串在前面,后面进行拼接
a+b+""//字符串在后面,先运算在拼接
三元运算符
x ? y : z
如果x==true,则结果为y,否则结果为z

包机制
为了更好的组织类,Java提供了包机制,用于区别类名的命名空间
包语句的语法格式为:
package pkg1[. pkg2[. pkg3...]];
一般利用公司域名倒置作为包名
为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用“import”语句可完成此功能
import package1[.package2...].(classname|*);
JavaDoc
JavaDoc是用来生成自己的API文档的
参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况

Java流程控制
用户交互Scanner
java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入
Scanner s = new Scanner(System.in);
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据
- next()方法

只输出一个hello
- nextLine方法

输出全部hello world
注意:
next():
- 一定要读取到有效字符后才可以结束输入
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串
nextLine()
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
- 可以获得空白
代码最后一定要关闭流[scanner.close();]
Scanner进阶使用

利用while循环计算平均数
顺序结构
Java的基本结构就是顺序结构

选择结构
if单选择结构
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
if双选择结构
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if多选择结构
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else{
//如果以上布尔表达式都不为true执行代码
}
注意:
- if语句至多有 1 个else语句,else语句在所有的else if语句之后
- if语句可以有若干个else if语句,他们必须在else语句之前
- 一旦其中一个else if 语句检测为true,其他的else if以及else语句都将跳过执行
嵌套的if结构
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}
}
switch多选择结构
switch case语句判断一个变量与一系列值中是否相等,每个值称为一个分支
switch 语句中的变量类型可以是:
- byte、short、int或者char
- 从Java SE 7开始switch 支持字符串String类型了
- 同时case标签必须为字符串常量或字面量

循环结构
while循环
结构:
while(布尔表达式){
//循环内容
}
注意:
- 只要布尔表达式为true,循环就会一直进行下去
- 我们大多数情况是会让循环停止下来的,我们需要一个表达式失效的方式来结束循环
- 少部分情况需要循环一直进行,比如服务器的请求响应监听等
- 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环
死循环
while(true){
}

do...while循环
do...while循环至少会执行一次
do{
//代码
}while(布尔表达式);

while和do...while的区别:
- while先判断后执行,do...while先执行后判断
- do...while总是保证循环体至少会被执行一次
for循环
for循环语句是最有效、最灵活的循环结构
for(初始化;布尔表达式;更新){
//代码
}

注意:
- 最先执行初始化步骤,可以声明一些初始化类型,但可初始化一个或多个循环控制变量,也可以是空语句
- 检测布尔表达式的值,如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句
- 执行一次循环后,更新循环控制变量
- 再次检测布尔表达式,循环执行上面的过程
九九乘法表

增强for循环
for(声明语句:表达式){
//代码
}

break continue
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句

continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

区别:
- break在任何循环语句的主体部分,均可用于break控制循环的流程
- break用于强行退出循环,不执行循环中剩余的语句
- continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
打印5行三角形

Java方法详解
方法是语句的集合,他们在一起执行一个工程
方法是解决一类问题的步骤的有序组合
方法是包含于类或对象中
方法在程序中被创建,在其他地方被引用

原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期的扩展
方法的定义
Java的方法类似于其他语言函数,是一段用来完成特定功能的代码片段
方法包含一个方法头和一个方法体
语法:
-
修饰符:这是可选的,告诉编译器如何调用该方法,定义了该方法的访问类型
-
返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void
-
方法名:是方法的实际名称。方法名和参数表共同构成方法签名
-
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传给方法的数据。
-
方法体:方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
方法调用
-
调用方法:对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择
-
当方法返回一个值的时候,方法调用通常被当作一个值。例如:
int larger = max(30,40); -
如果方法返回值是void,方法调用一定是一条语句。
System.out.println("Hello");

方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法重载的规则:
1>方法名称必须相同。
2>参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
3>方法的返回类型可以相同也可以不同。
4>仅仅返回类型不同不足以成为方法的重载。
-
实现理论:方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器会报错。
命令行传参
有时候你希望运行一个程序的时候再传递给它消息。这要靠传递命令行参数给main()函数实现
public class CommandLine{
public static void main(String args[]){
for(int i=0;i<args.length;i++){
System.out.println("args[" + i +"]:" + args[i]);
}
}
}

方法递归
递归就是a方法调用a方法,就是自己调用自己
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环
- 递归体:什么时候需要调用自身方法=""
![]()
能不用递归就不用递归
Java数组
数组的定义
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
其中,每一个数据称作一个数组元素,每一个数组元素可以通过一个下标来访问他们
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组
dataType[] arrayRefVar; //首选方法 或 dataType arrayRefVar[]; //效果相同 但不是首选方法 -
Java语言使用new操作符来创建数组
dataType[] arrayRefVar = new dataType[arraySize]; -
数组的元素是通过索引访问的,数组索引从0开始
-
获取数组长度
arrays.length

内存分析
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
下标越界
三种初始化
-
静态初始化
int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)}; -
动态初始化
int[] a = new int[2]; a[0]=1; a[1]=2; -
数组的默认初始化
数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
数组的四个基本特点
- 长度是确定的,数组一旦被创建,他的大小就是不可以改变的
- 元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任意数据类型,包括基本类型和引用类型
- 数组变量属引用类型,数组也可以看成是对象,数组中的每一个元素相当于该对象的成员变量
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的
小结:
- 数组是相同数据类型的有序集合
- 数组也是对象,数组元素相当于对象的成员变量
- 数组长度是确定的,不可变的,如果越界,则报ArrayIndexOutOfBoundsException
数组的使用


多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
-
二维数组
int a[][] = new int[2][5];

Arrays类
-
数组的工具类java.util.Arrays
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用
-
具有以下常用功能
给数组赋值:通过fill方法
给数组排序:通过sort方法,按升序
比较数组:通过equals方法比较数组中的元素是否相等
查找数组元素:通过binarySearch方法对排序好的数组进行二分查找法操作

冒泡排序

稀疏数组
需求:编写五子棋游戏中,有存盘退出和续上盘的功能
稀疏数组介绍:当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值的个数:"+sum);
//2.创建一个稀疏数组的数组
int[][] array2 = new int[sum+1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
//遍历二维数组,将非0的值存放稀疏数组中
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if(array1[i][j]!=0){
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
System.out.println("稀疏数组" );
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"
+array2[i][1]+"\t"
+array2[i][2]+"\t");
}
输出结果:

面向对象编程
面向过程&面向对象
-
面向过程思想
步骤简单清晰,第一步做什么,第二布做什么
面对过程适合处理一些较为简单的问题
-
面向对象思想
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
面向对象适合处理复杂的问题,适合处理需要多人协作的问题
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到围观操作,仍需要面向过程的思路去处理
什么是面向对象
面向对象的编程(Object-Oriented Programming,OOP)
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
三大特征:
- 封装
- 继承
- 多态
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
从代码运行角度考虑是先有类后有对象。类是对象的模板
回顾方法的调用
静态方法:

非静态方法:


值传递:

change中的a 为形参,调用change函数并没有传递返回值,所以a依然为1
引用传递:

类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是不能代表某一个具体的事物
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
对象是抽象概念的具体实力
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
创建与初始化对象
使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间以外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有两个特点:
- 必须类和名字相同
- 必须没有返回类型,也不能写void
作用:
- new本质在调用构造方法
- 初始化对象的值
注意点:
- 定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造
一个类即使什么都不写,他也会存在一个方法
一旦定义了有参构造,无参就必须显示定义

生成构造器的快捷键:alt+insert

类似于c中的指针
小结类与对象
类与对象:
- 类是一个模板:抽象 对象是一个具体的实例
方法:
- 定义、调用
对应的引用
- 引用类型: 基本类型(8)
- 对象是通过引用来操作的:栈----->堆
属性:字段 Filed 成员变量
默认初始化:
- 数字: 0 0.0
- char: u0000
- booLean: false
- 引用: null
- 修饰符 属性类型 属性名 = 属性值
对象的创建和使用:
- 必须使用new 关键字创造对象 ,构造器 Person lele = new Person();
- 对象的属性 lele.name
- 对象的方法 lele.sleep()
类:
- 静态的属性
- 动态的方法
封装
该露的露,该藏的藏
我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是指仅暴露少量的方法给外部使用
属性私有,get/set
快捷键 alt + insert 自动生成get/set

封装的意义:
- 提高程序安全性,保护数据
- 隐藏代码实现细节
- 统一接口
- 系统可维护性增加了
如上图,当输入年龄不合法时,可以直接再封装中设置条件进行筛选
继承
extends的意思是“扩展”。子类是父类的扩展
JAVA中类只有单继承,没有多继承
继承是类和类之间的关系,除此之外,类和类之间的关系还有依赖、组合、聚合等

子类可以继承父类的所有方法,如图

子类中什么方法也没有,但是依然可以输出数据,证明继承了父类的所有方法
修饰符:public 公共的
private 私有的
修饰符为私有时,子类不能继承父类

在JAVA中,所有类都默认继承Object类

ctrl + H快捷键打开族谱
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或构造方法中
- super和this并不能同时调用构造方法
与this的对比:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
- this没有继承也可以使用
- super只能在继承条件才可以使用
构造方法:
- this();本类的构造
- super();父类的构造
重写:是方法的重写,与属性无关


如上图,有无static的区别
有static时,输出结果为“A=>test() B=>test()”
无static时,输出结果为“A=>test() A=>test()”
即 b是A new出来的对象,因此调用了A的方法,因为静态方法是类的方法,而非静态方法是对象的方法,所以,有static时,b 调用了B类的方法,因为b是用b类定义的,没有static时,b调用的是对象的方法,而b是用A类new的
静态属于类,非静态属于对象
重写总结:
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符范围可以扩大,但是不能缩小 public>protected>default>private
- 抛出的异常范围可以缩小但不能扩大
为什么需要重写:
- 父类的功能子类不一定需要或者不一定满足
多态

如图,eat方法只在子类有,而父类没有,所以父类不能调用
而子类可以调用自己的或者继承父类的方法
父类可以指向子类,但是不能调用子类独有的方法
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常ClassCastException
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象
有些方法不能被重写:
- static 属于类,不属于实例
- final 常量
- private方法
instanceof关键字

公式:System.out.println(X instanceof Y); 能不能编译通过要看X、Y有没有父子关系
强制转换:

父亲不能直接拿儿子的方法,必选先让父亲装作儿子才能使用
子类转化为父类,可能会丢失自己本来的一些方法
注意:
- 父类引用子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转移,强制转换
- 方便方法的调用,减少重复的代码
static关键字

静态变量对于所有对象共享,当直接使用类去调用得到说明是静态变量
如果不是静态变量则如上图score

方法也是同理

静态代码块
可以通过静态导入包来直接实现输出方法

final是断子绝孙修饰符,一旦被final修饰就不能被继承

抽象类
abstra修饰符可以用来修饰方法,亦可以用来修饰类,如果他修饰类,那么就叫抽象类

抽象类的所有方法,在继承时必须重写

但如果子类也是抽象类,则不需要重写,交给他的孙子辈
特点:
- 不能new这个抽象类,只能靠子类去实现它 约束
- 抽象方法必须在抽象类中
- 抽象类中可以写普通的方法
抽象的抽像:约束
接口
只有规范,无法写方法
接口就是规范,定义的是一组规则,体现了世界中“如果你是...则必须能...”的思想
接口的本质是契约,就像人类的法律一样,制定好以后大家都遵守
接口声明的关键字是:interface

在idea中,接口与普通类有明显区别

如果要实现接口里的类,就必须重写接口中的所有方法,不然会报错
接口可以多继承

总结:接口的作用
- 约束
- 定义一些方法,让不同的人实现
- 方法public abstract
- public static final
- 接口不能被实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
异常机制
异常指程序运行中出现了不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等
异常发生在程序运行期间,他影响了正常的程序执行流程
异常分为三种:
- 检查性异常:最具代表性的是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单的忽略
- 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时被忽略
- 错误:错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如:当栈溢出时,一个错误就发生了,他们在编译时也检查不到的
区别:error是灾难性的致命错误,是程序无法控制和处理的
exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
异常处理机制
关键字:try catch finally throw throws

try catch 必须有 finally可以没有
无论如何,finally一定会执行

catch(); 括号里是想要捕获的异常名称
快捷键:ctrl alt+t

throw是在方法中主动抛出异常 throws是方法处理不了这个异常,抛出方法以外
自定义异常

总结:
- 处理运行时异常时,采用逻辑去合理规避同时辅助try—catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try—catch,处理潜在异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 尽量添加finally语句块去释放占用的资源



浙公网安备 33010602011771号