一、命令行基本命令
pwd
查看当前目录完整路径
ls
查看当前目录中所有文件
ls -l
查看当前目录中所有文件的详细信息
mkdir 文件夹名称
在当前目录下创建新文件夹
cd ..
返回上级目录
cd 目录完整路径
进入到指定目录
echo 123456>1.doc
写内容123456到文件1.doc,会在当前目录中新建文件1.doc
cat 1.doc
显示内容-->123456
rm 1.doc
删除文件
rmdir 文件夹名称
删除文件夹
rm -rf 目录名字
-r 就是向下递归,不管有多少级目录,一并删除
-f 就是直接强行删除,不作任何提示的意思
cp 1.txt 目标位置路径
复制文件
mv 1.txt 目标位置路径
移动文件
二、JDK JRE JVM的关系
JDK=JRE+Java开发工具(javac.exe,java.exe,javadoc.exe)
JRE=JVM+Java核心类库
三、编译运行Java代码
配置环境变量:
JAVA_HOME=bin的上一层目录
path=%JAVA_HOME%\bin
编写Java代码规范:
1、在一个java源文件中可以有多个类,但是只能有一个类可以申明为public。而且要求申明为public的类的类名必须与源文件名相同
2、程序的入口是main()方法。格式是固定的
3、输出语句:
System.out.println();//先输出数据然后换行
System.out.print();//只输出数据
4、每一行执行语句都以;结束
5、编译后生成一个或多个字节码文件,字节码文件的名称和Java源文件中的类名一致
vim HelloWorld.java
写入
class HelloChina{
public static void main(String[] args){
System.out.println("Hello,World!");
}
}
javac HelloWorld.java
格式:javac 源文件名.java
java HelloChina
格式:java 类名
四、注释 comments
作用:
对程序进行解释说明,增强可读性
调试所写的代码 (单行注释和多行注释的内容不参与编译)
//单行注释
/*
多行注释
*/
/**
*文档注释
*可以被JDK解析,生成说明文档index.html
*/
javadoc -d HelloWorld文件夹名称 -author -version HelloWorld.java
生成HelloWorld文件夹,index.html
五、软件
一系列按照特定顺序组织的计算机数据和指令的集合。分为系统软件、应用软件
系统软件:Windows,mac os, linux,unix,android,ios
应用软件:word,ppt,画图板
人机交互方式:图形化界面vs命令行方式
应用程序=算法+数据结构
六、java简介
1、计算机发展史:
机器语言
汇编语言
高级语言
-面向过程:C,Pascal,Fortran
-面向对象:java
2、java语言应用领域:web开发,大数据开发,Android应用程序开发
3、Java语言的特点:
面向对象性
-两个要素:类,对象
-三个特性:封装、继承、多态
健壮性
七、关键字和保留字
关键字:被Java语言赋予了特殊含义,用作专门用途的字符串
关键字中所有字母小写
保留字:以后的Java版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字,如:goto/const
八、标识符
标识符:各种变量、方法、类等要素命名时使用的字符序列,凡是自己可以起名字的地方都叫标识符
命名规则:
1、由26个字母大小写、0-9,_或$组成
2、数字不可开头
3、不可使用关键字和保留字
4、严格区分大小写
5、不能包含空格
命名规范:
1、包名:多个单词,所有字母小写xxxyyy
2、类名、接口名:所有单词首字母大写XxxYyy
3、变量名、方法名:第一个单词首字母小写,第二个单词开始首字母大写xxxYyy
4、常量名:所有字母大写,单词用下划线_连接XXX_YYY
5、见名知意
九、变量
变量的格式:数据类型 变量名=变量值
说明:
1、变量必须先声明,再使用
2、变量都定义在其作用域内,出了作用域无效
3、同一个作用域中,不能有两个同名的变量
十、数据类型
基础数据类型
引用数据类型:string
1、byte 1字节=8bit,范围:-128-127
2、声明long型变量,以l或L结尾
3、声明float变量时,以f或F结尾
4、声明char变量时使用' ',内部只能写一个字符,'\n'换行符,'\t'制表符,'\u0043'Unicode值表示字符串常量
5、float尾数可以精确到7位有效数字
十一、类型转换
只讨论7中基本数据类型变量间的运算,不包含boolean类型的
1、自动类型转换:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。容量表示数的范围和大小
byte/char/short-->int-->long-->float-->double
特别注意:byte/char/short做运算,结果为int类型
2、强制类型转换:自动类型转换的逆运算
需要使用强转符:(),可能会导致精度损失,如截断操作 double转int
long l = 123213;//没有加L,但不报错,是由于自动类型转换,int转long
十二、string
声明string类型变量时,使用" "
string可以和8种基本数据类型变量做运算,且运算为连接运算,+
运算结果仍然为String类型
十三、运算符
1、算术运算符
+ - * / %取余 ++自加1 --自减1
% 运算结果的符号(正负)和被模数一样
2、赋值运算符
= += -= *= /= %=
num += 2;//相当于num = num + 2,但不会改变变量本身的数据类型
3、比较运算符
== != < > <= >= instanceof
结果为boolean类型
4、逻辑运算符
&逻辑与 | 逻辑或 !逻辑非 &&短路与 ||短路或 ^逻辑异或
5、位运算符
<<左移 二进制位向左移两位 >>右移
6、三元运算符
又称三目运算符
(条件表达式)?表达式1:表达式2
条件表达式为true,执行表达式1
条件表达式为false,执行表达式2
十四、如何从键盘获取不同类型的变量
1、导包:import java.util.Scanner;
2、Scanner的实例化:Scanner scan = new Scanner(System.in);
3、调用Scanner类的相关方法,来获取指定类型的变量
scan.next();
scan.nextInt();
scan.nextDouble();
需要根据相应的方法,来输入指定类型的值,如果输入的数据类型不匹配,则会报错
十五、分支语句
1、switch-case
switch(表达式){
case 常量1:
执行语句1;
//break;
case 常量2:
执行语句2;
//break;
}
根据switch表达式中的值,依次匹配各个case中的常量。一旦匹配成功,则进入相应case结构中,调用其执行语句。当调用完执行语句之后,则仍然继续向下执行其他case结构中的执行语句,直到遇到break关键字或者此switch-case的末尾结束为止
break可以使用在switch-case结构中,表示一旦执行到此关键字,就跳出switch-case结构
switch中表达式只能是以下6种数据类型之一:byte short char int 枚举类型 String类型
case之后只能声明常量,不能声明范围
default:相当与if-else中的else
2、for循环
循环四要素:
1初始化条件
2循环条件
3循环体
4迭代条件
for(1初始化条件;2循环条件;4迭代条件){
3循环体;
}
执行过程:1-2-3-4-2-3-4
3、while循环
1初始化条件
while(2循环条件){//boolean类型
3循环体;
4迭代条件;//一旦丢了,就可能导致死循环
}
执行过程:1-2-3-4-2-3-4
for循环和while循环可以相互转换,区别:初始化条件部分的作用域不同
4、do-while循环
1初始化条件
do{
3循环体;
4迭代条件;
}while(2循环条件);
执行过程:1-3-4-2-3-4-2
至少会执行一次循环体
5、break continue关键字
break 使用范围:switch-case 循环结构中,作用:结束当前循环
continue 使用范围:循环结构中,作用:结束当次循环
6、嵌套循环
将一个循环结构A(内层循环)声明在另一个循环结构B(外层循环)的循环体中,构成嵌套循环
内层循环结构遍历一遍,只相当于外层循环体执行一次
假设外层循环需要执行m次,内层循环需要执行n次,此时内层循环的循环体执行了m*n次
外层循环控制行数,内层循环控制列数
十六、数组
1、多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理
2、相关概念:
数组名
元素
角标、下标、索引
数组的长度、元素的个数
3、特点:
有序排列
创建数组对象会在内存中开辟一整块连续的空间
长度不能修改
4、分类:
按照维数:一维数组、二维数组、……
按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组
5、一维数组
//基本数据类型的声明和初始化
int num;//声明
num = 10;//初始化
int id = 1001;//声明+初始化
//一维数组的声明和初始化
int[] ids;//声明
//静态初始化:数组的初始化和数组元素的赋值操作同时进行
ids = new int[]{1001,1002,1003,1004};
//动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[] names = new String[5];//数组一旦初始化完成,其长度就确定了
//调用数组指定位置的元素:通过角标的方式调用,角标从0开始,到数组的长度-1结束
names[0] = "anna";
//获取数组的长度
names.length
//遍历数组
for(i=0;i<names.length;i++){
System.out.println(name[i]);
}
//默认初始化值
数组元素是整型:默认为0
数组元素为浮点型:0.0
数组元素是char型:0
数组元素是boolean型:false
数组元素是引用数据类型:null
6、二维数组
//二维数组的声明和初始化
int[][] arr1;//声明
//静态初始化:数组的初始化和数组元素的赋值操作同时进行
arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
//动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[][] arr2 = new String[3][2];//第二个可以为空
//调用数组指定位置的元素:通过角标的方式调用,角标从0开始,到数组的长度-1结束
arr1[0][0] = 1;
//获取数组的长度
arr1.length //3
arr1[1].length //2
//遍历数组
for(i=0;i<arr1.length;i++){
for(j=0;j<arr1[i].length;j++){
System.out.println(arr1[i][j]);
}
System.out.println();//换行
}
//默认初始化值
int[][] arr = new int[4][3];
外层元素:arr[0]
内存元素:arr[0][0]
针对于初始化方式一:int[][] arr = new int[4][3];
外层元素的初始化值为:地址值
内层元素的初始化值为:与一维数组初始化情况相同
针对于初始化方式二:int[][] arr = new int[4][];
外层元素的初始化值为:null
内存元素的初始化值为:不能调用,否则报错
7、二分法查找
//前提:查找的数组有序
int[] arr2 = new int[]{-98,45,34,4,66,0,-32};
int dest1 = 45;
int head = 0;//初始的首索引
int end = arr2.length - 1;//初始的末索引
boolean isFlag1 = true;
while(head <= end){
int middle = (head + end) / 2;
if(dest1 == arr2[middle]){
System.out.println("找到了指定的元素,位置为:" + middle);
isFlag1 = false;
break;
}else if(arr2[middle]>dest1){
end = middle - 1;
}else{
head = middle + 1;
}
}
if(isFlag1){
System.out.println("不存在元素:" + dest1);
}
8、冒泡排序
public class BubbleSortTest{
public static void main(String[] args){
int[] arr = new int[]{-98,45,34,4,66,0,-32};
for(int i = 0; i < arr.length - 1; i ++){
for(int j = 0; j < arr.length - 1 - i; j ++){
if(arr[j] > arr[j + 1]{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
9、Arrays工具类
java.util.Arrays
public class ArrrayTest{
public static void main(String[] args){
int[] arr1 = new int[]{1,2,3,4};
int[] arr2 = new int[]{1,3,2,4};
boolean isEquals = Arrays.equals(arr1,arr2);
System.out.println(isEquals);
System.out.println(Arrays.toString(arr1));
}
}
10、异常
数组角标越界异常:ArrayIndexOutOfBoundException
空指针异常:NullPointerException
十七、面向对象 OOP
1、面向对象学习的三条主线:
- Java类及类的成员
属性、方法、构造器、代码块、内部类
- 面向对象的三个特征
封装性、继承性、多态性
- 关键字
this/super/static/final/abstract/interface/package/import
2、类、对象、属性、方法
类:对一类事物的描述,是抽象的概念上的定义
对象:是实际存在的该类事物的每个个体,也称为实例instance
属性=成员变量=field=域、字段
方法=成员方法=函数=method
创建类的对象=类的实例化=实例化类
类和对象的使用:创建类,设计类的成员;创建类的对象;通过“对象.属性”或“对象.方法”调用对象的结构
类的对象被创建多次时,每个对象都有独立的类的属性
3、面向过程VS面向对象
4、对象的内存解析
堆heap:存放对象实例,对象的非static属性
栈stack:存储局部变量
方法区:类信息、常量、静态变量、即时编译器编译后的代码
5、属性/成员变量 VS 局部变量
相同点:
- 定义变量的格式:数据类型 变量名=变量值
- 先声明后使用
- 变量都有其对应的作用域
不同点:
- 在类中声明的位置不同
属性:直接定义在类的一对{}内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
- 关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符(private 缺省 protected public),目前大部分是缺省
局部变量:不可使用权限修饰符
- 默认初始化值不同
属性:类的属性根据其类型,都有默认初始化值
整型(byte short int long):0
浮点型(float double):0.0
字符型(char):0或'\u0000'
布尔型(boolean):false
引用数据类型(类 数组 接口):null
局部变量:没有默认初始化值
调用局部变量之前,一定要显式赋值
在形参调用之前,赋值即可
6、方法的声明
//形参列表可以有,可以没有,可以是一个,也可以是多个
权限修饰符 返回值类型 方法名(形参列表){
方法体
}
注意:static final abstract来修饰的方法
- 4种权限修饰符:private public protected 缺省,默认方法的权限修饰符先都使用public
- 返回值类型:有返回值VS没有返回值
有返回值,必须在方法声明时,指定返回值的类型。同时方法中需要使用return关键字来返回指定类型的变量或常量:return 数据;
没有返回值,方法声明时使用void,方法中不使用return,但使用的话只能:return;,表示结束此方法
- 方法名:属于标识符,见名知意
- 形参列表:数据类型1 形参1,数据类型2 形参2,……
- 方法体:方法功能的体现
return关键字的使用:
使用范围:方法体中
作用:结束方法;针对有返回值的方法,返回所要的数据
- 方法的使用:可以调用当前类的属性或方法
递归方法:方法A中又调用方法A
方法中不可定义方法
7、匿名对象
创建的对象没有显式的赋给一个变量名
只能调用一次
8、方法的重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同
通过对象调用方法时,如何确定某一个指定的方法:方法名-->参数列表
9、可变个数形参的方法
格式:数据类型... 变量名
调用可变个数形参的方法时,传入的参数个数可以是0个,1个,2个……
可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
可变个数形参在方法的形参中,必须声明在末尾,且最多只能声明一个可变个数形参
10、方法参数的值传递机制
方法必须由其所在类或对象调用才有意义
形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
关于变量的赋值:
变量是基本数据类型,赋值是变量所保存的数据值
变量是引用数据类型,赋值是变量所保存的数据的内存地址
值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值
11、递归方法
递归方法:一个方法内调用它本身
方法递归包含一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环
//计算1-n之间所有自然数的和
public int getSum(int n){
if(n == 1){
return 1;
}else{
return n + getSum(n - 1);
}
}
12、面向对象的特征-封装性
当我们创建一个类的对象后,我们可以通过对象.属性的方式,对对象的属性进行赋值。这里,赋值操作受属性的数据类型和存储范围的制约。除此之外,没有其他的制约条件。但是实际问题中,往往需要加入额外的限制条件。这个条件就不能在属性声明时体现,只能通过方法进行限制条件的添加。同时需要避免用户再使用对象.属性的方式对属性进行赋值,则需要将属性声明为私有的private,此时,针对属性就体现了封装性。
封装性的体现:将类的属性私有化(private),同时提供公共的方法来设置和获取此属性的值
封装性的体现需要权限修饰符来配合
修饰类:缺省 public
修饰类的内部结构:属性、方法、构造器、内部类:private 缺省 protected public
13、构造器
又称构造方法、constructor
作用:创建对象 (new + 构造器);初始化对象的属性
如果没有显式的定义类的构造器,则系统默认提供一个空参的构造器,但是一旦显式定义了类的构造器,则系统不再提供默认的空参的构造器
定义构造器的格式:权限修饰符 类名(形参列表){}
14、this
this可以用来修饰属性、方法、构造器
this修饰属性和方法:理解为当前对象或当前正在创建的对象
在类的方法中,可以使用this.属性或this.方法的方式,调用当前对象属性和方法。但是通常情况下,我们选择省略this. 特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用this.变量的方式,表明此变量是属性而非形参。
在类的构造器中,我们可以使用this.属性或this.方法的方式,调用当前正在创建的对象属性或方法。但是通常情况下,我们选择省略this. 特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用this.变量的方式,表明此变量是属性,而非形参。
this调用构造器:
在类的构造器中,可以显式的使用this(形参列表)方式调用本类中指定的其他构造器
规定:this(形参列表)必须声明在当前构造器的首行,且最多只能声明一个
15、package
package包:实现项目中类的管理,声明类或接口所属的包,声明在源文件的首行
package属于标识符,见名知意
每.一次,代表一层文件目录
同一个包下,不能命名同名的类和接口
MVC:视图模型层view,控制器层controller,数据模型层model
16、import
import导入:在源文件中显式的使用import结构导入指定包下的类、接口
声明在包的声明和类的声明之间
如果需要导入多个结构,则并列写出即可
可以使用XXX.*的方式,表示可以导入XXX包下的所有结构
如果使用的类或接口是java.lang包下定义的,则可以省略import结构
如果使用的类或接口是本包下定义的,则可以省略import结构
17、面向对象的特征-继承性
好处:
提高了代码的复用性,减少冗余的代码
便于功能的扩展
为之后多态性的使用提供前提
继承性的格式:class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
一旦A继承了B,子类A就获取了父类B声明的结构:属性和方法
子类继承父类后可以声明自己特有的属性或方法,实现功能的拓展
如果没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
18、方法的重写override/overwrite
子类继承父类后,可以对父类中同名同参数的方法进行覆盖操作
方法的声明:
权限修饰符 返回值类型 方法名(形参列表){
方法体
}
子类中叫重写的方法,父类中叫被重写的方法
子类重写的方法的方法名和形参列表与父类相同
子类重写的方法的权限修饰符不小于父类的范围
特殊情况:子类不能重写父类中声明为private权限的方法
返回值类型:父类被重写的方法的返回值类型是void,则子类只能是void
父类被重写的方法的返回值类型是A类型,则子类可以是A类型及其子类
父类被重写的方法的返回值类型是基本数据类型,则子类必须相同
子类重写的方法抛出的异常类型不大于父类
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(非重写,static的方法不能被覆盖,随着的类的加载而加载)
19、权限修饰符
使用范围:
20、super
父类的,用来调用属性、方法、构造器
使用:可以在子类的方法或构造器中,通过使用super.属性或super.方法的方式,显式的调用父类中声明的属性或方法。通常省略super.
特殊情况:
当子类和父类中定义了同名的属性时,要想在子类中调用父类中声明的属性,则必须显式的使用super.属性的方式,表明调用的是父类中声明的属性
当子类重写了父类的方法时,要想在子类中调用父类中被重写的方法,则必须显式的使用super.方法的方式,表明调用的是父类中被重写的方法
super调用构造器:
可以在子类的构造器中显式的使用super(形参列表)的方式,调用父类中声明的指定的构造器
super(形参列表)的使用,必须声明在子类构造器的首行
在类的构造器中,针对于this(形参列表)或super(形参列表)只能二选一,不能同时出现
没有显式声明时,默认调用的是父类中空参的构造器
在类的多个构造器中,至少有一个类的构造器中使用了super(形参列表),调用父类中的构造器
21、子类对象实例化
22、多态性
对象的多态性:父类的引用指向子类的对象(子类的对象赋给父类的引用)
多态的使用:虚拟方法调用
有了对象的多态性,编译期只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法,即当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法
多态性的使用前提:类的继承关系;方法的重写
对象的多态性:只适用于方法(编译看左边,运行看右边),不适用于属性(编译和运行都看左边)
23、instanceof关键字
a instanceof A:判断对象a是否是类A的实例
用于对象向下类型转换时避免ClassCastException的异常,在向下转型之前先进行instanceof判断,true-->向下转型
24、Object类
Object类是所有Java类的根父类
Object类中的属性和方法具有通用性
Object类只声明了一个空参的构造器
25、equals方法 VS ==运算符
==:如果比较的是基本数据类型变量:比较保存的数据是否相等(不一定类型要相同)
如果比较的是引用数据类型变量:比较地址值是否相同,即两个引用是否指向同一个对象实体
equals:只适用于引用数据类型
Object类中equals()的定义:
public boolean equals(Object obj){
return (this == obj);
}
说明:Object类中定义的equals()和==的作用是相同的
String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址,而是对象的实体内容
26、toString()方法
当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
A a = new A();
System.out.println(a.toString());//com.qin.java.A@15db9743
System.out.println(a);//com.qin.java.A@15db9743
String、Date、File、包装类等都重写了Object类中的toString()方法。重写以后,在调用对象的toString()时,返回实体内容信息
27、单元测试
选中当前工程-右键选择:build path-add libraries-JUnit4
创建Java类,进行单元测试。要求此类是public的,提供公共的无参的构造器
此类中声明单元测试方法。要求方法的权限是public,没有返回值、形参。加注解@Test,导入import org.junit.Test;
28、包装类 Wrapper
针对八种基本数据类型定义相应的引用类型-包装类(封装类)
基本数据类型和包装类的转换
自动装箱自动拆箱
29、static关键字
静态的,可以用来修饰属性、方法、代码块、内部类
静态属性(static修饰的属性)-静态变量(类变量)
static String name;
非静态变量(实例变量):创建对象独立拥有一套类中的非静态属性
静态变量:创建对象共享一个静态变量
静态变量随着类的加载而加载,静态变量的加载要早于对象的创建,由于类只加载一次,所以静态变量在内存中只会存在一份(方法区的静态域中)
静态方法(static修饰的方法):随着类的加载而加载,通过类.静态方法的方式调用
静态方法中只能调用静态的属性和方法,非静态方法中可以调用静态和非静态的属性和方法
静态方法中不能使用static/super关键字
30、单例设计模式Singleton
采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
饿汉式:对象加载时间过长,但是线程安全的
public class SingletonTest1{
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);//true对象只有一个
}
}
class Bank{
//1、私有化的构造器-避免在类的外部造对象
private Bank(){
}
//2、内部创建类的对象-私有化的对象在类的外部调用不了,只能通过方法调用
//4、要求此对象也必须声明为静态的-静态方法只能调用静态的结构
private static Bank instance = new Bank();
//3、提供公共的静态的方法,返回类的对象-非静态的方法只能通过new出的对象去调用,静态方法随着类的加载而加载,通过类.静态方法的方式调用
public static Bank getInstance(){
return instance;
}
}
懒汉式:延迟对象的创建,但是线程不安全
public class SingletonTest2{
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2);//true
}
}
class Order{
//1、私有化类的构造器
private Order(){
}
//2、声明当前类的对象,没有初始化
private static Order instance = null;
//3、声明公共的静态的返回当前对象的方法
public static Order getInstance(){
if(instance == null){
instance = new Order();
}
return instance;
}
}
31、main方法
main()方法作为程序的入口
是一个普通的静态方法
可以作为与控制台交互的一种方式
32、代码块
类的成员之一,又称为初始化块
作用:用来初始化对象、类
如果有修饰的话,只能用static
分类:静态代码块VS非静态代码块
静态代码块:内部可以有输出语句,随着类的加载而自动执行一次。作用:初始化类的信息
非静态代码块:内部可以有输出语句,随着对象的创建而自动执行。每创建一个对象,就执行一次。作用:可以在创建对象时,对对象的属性等进行初始化
静态代码块的执行优先于非静态代码块。如果一个类中定义了多个静态代码块/非静态代码块,按声明的先后顺序执行。
33、属性赋值的位置
1默认初始化
2显式初始化/5在代码块中赋值
3构造器中初始化
4有了对象之后,可以通过对象.属性或对象.方法的方式,进行赋值
执行顺序:1-2/5-3-4
34、final关键字
最终的
用来修饰类、方法、变量
修饰类:此类不能被继承,如String/System/StringBuffer
修饰方法:此方法不能被重写,如Object类中getClass()
修饰变量:此变量就称为是一个常量。final修饰属性可以考虑赋值的位置:2显式初始化、5在代码块中赋值、3构造器中初始化
修饰局部变量:修饰形参表明此形参是一个常量,当调用此方法时给常量形参赋一个实参,一旦赋值后只能在方法体内使用此形参,不能进行重新赋值
static final用来修饰属性:全局常量
35、抽象类 抽象方法
abstract关键字
抽象的,用来修饰类、方法
抽象类:没有具体的实例,不可实例化(new对象)。抽象类中一定有构造器(子类对象的实例化时调用)
抽象方法:只有方法的声明,没有方法体。包含抽象方法的类一定是抽象类
abstract不能用来修饰属性、构造器等结构,不能用来修饰私有方法、静态方法、final的方法、final的类
36、接口
继承是是不是的关系,接口是能不能的关系
接口的使用:interface定义
接口和类是并列的两个结构
定义接口中的成员
全局常量:(public static final)可以省略不写
抽象方法:(public abstract)可以省略不写 void 方法()
接口中不能定义构造器,意味着接口不可以实例化
静态方法:static关键字修饰,只能通过接口来调用
默认方法:default修饰,通过实现类的对象调用。
如果实现类重写了接口中的默认方法,调用的是重写后的方法。
如果子类或实现类继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认使用的是父类中的同名同参数的方法(类优先原则)。
如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错(接口冲突)。
Java中,接口通过让类去实现implements的方式来使用,如果实现类覆盖了接口中的所有抽象方法,则实现类就可以实例化。如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
Java类可以实现多个接口。先写继承再写接口的实现
接口和接口之间可以继承,允许多继承
37、内部类
将类A声明在类B中,则类A为内部类,类B为外部类
内部类:成员内部类(静态的、非静态的)VS局部内部类(方法内、代码块内、构造器内)
成员内部类:作为外部类的成员,调用外部类的结构,可以被static修饰,可以被4种不同的权限修饰
作为一个类,可以定义属性、方法、构造器等。可以被final修饰,表示此类不能被继承,可以被abstract修饰
十八、异常处理
1、分类
1.1 error:Java虚拟机无法解决的严重问题,一般不进行处理。如StackOverflowError、OOM
public class reflect {
public static void main(String[] args) {
//Exception in thread "main" java.lang.StackOverflowError
main(args);
//Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Integer[] arr = new Integer[1024*1024*1024];
}
1.2 exception:如空指针异常、读取文件异常、网络连接中断异常、数组角标越界异常
编译时异常
运行时异常
2、异常处理
2.1 抛,程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出,一旦抛出对象后,后续的代码不再执行。
关于异常对象的产生:1系统自动生成的异常对象。2手动生成一个异常对象,并抛出(throw)
2.2 try-catch-finally:抓,真正的将异常处理掉了。finally是可选的,finally里声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有return语句的情况。
throws:抓,“throws+异常类型”写在方法的声明处,指明此方法执行时,可能会抛出的异常类型。只是将异常抛给了方法的调用者,并没有真正将异常处理掉
public class reflect {
public static void main(String[] args) throws IOException {
File file = new File("hello.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.println(data);
data = fis.read();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
try {
fis.close();//一定会执行
}catch (Exception e){
e.printStackTrace();
System.out.println("haha");
}
}
}
}
方法重写的规则之一:
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch方式处理。
执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throw的方式进行处理,而执行的方法a可以考虑使用try-catch方式进行处理。
2.3 用户自定义异常
步骤:
继承于现有的异常结构:RuntimeException/Exception
提供全局常量:serialVersionUID
提供重载的构造器