1. 面向对象的思想
1.1. 开发软件的设计思路:
1.1.1. 面向过程:解决复杂业务是按照业务操作的自然顺序,从前到后,依次按照步骤完成
1.1.2. 面向对象:解决复杂业务是将业务拆分成若干个环节,在每个环节上找到可以完成任务的对象,调用业务方法,完成整个业务
2. 封装:将数据私有化,提供公共的方法给外界程序调用
2.1. 封装的原因:根据业务需要将外界的数据进行业务处理时,用户只需要输入数据,通过公共的赋值的方法进行具体业务判断
2.2. 封装的优势:让代码更好理解与维护;增加代码安全性
3. 包的概念:将java文件按照业务规则分类管理
3.1. 包命名的规则:com.公司名.项目名.功能模块名
3.2. 常用的工具包
3.2.1. java.lang:打包基础的类
3.2.2. java.io:包含输入输出功能的函数
3.2.3. java.util:包含一些重要的工具
3.3. 不在同一个包下的类相互调用,需要使用import导入
4. 类的访问修饰符
4.1. 修饰类的修饰符可以是public或者默认
4.2. 一个java文件中只能存在一个public修饰的同名类
4.3. 多个类在同一包名下,可以互相调用,不用使用import关键字导入包名
4.4. 类成员的访问修饰符有4中
4.4.1. Private :只能在本类使用
4.4.2. Default:只能在同包的其他类中使用
4.4.3. Public:其他类都可以使用
4.4.4. Protected:同一类,同一包可使用。不同包的类要使用,必须是该类的子类
5. 继承
5.1. 子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法
5.2. 继承是单方向的,即派生类可以继承和访问基类中的成员,但基类则无法访问派生类中的成员
5.3. 继承所描述的是“is-a”的关系,设计类与类的关系时,如果符合is-a的条件,则可以考虑设计继承关系
5.4. 子类可以拥有父类公开的属性和方法
5.5. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展
5.6. 子类可以用自己的方式实现父类的方法(方法重写)
6. 继承关系下的构造方法执行规则
6.1. 使用任何类创建对象时,JVM都会提供一个默认的无参数的构造方法
6.2. 如果在类中设计了有参数的构造方法,则JVM不在提供默认的无参数的构造方法
6.3. 子类的构造方法不能继承父类的构造方法,只能调用父类的构造方法,并且调用语句位于子类构造方法的第一句
7. 子类重写父类的方法
7.1. 方法重写:方法名,参数列表,返回值都要保持一致
7.2. 子类方法的访问级别不能低于父类相应方法的访问级别
7.3. 子类重写的方法可以改变抛出异常的类型,但是异常类型不能大于父类抛出的异常
8. Super关键字的用法
8.1. Super关键字在类中使用时,调用当前类的父类对象的属性或方法
8.2. 每个类都拥有最顶级的父类Object,可以通过重写Object的toString()方法,打印当前类的信息
8.3. 在主程序main方法中,可以通过System.out.print()方法直接打印对象的信息,不需要手动调用toString();
8.4. 开发中super常用于调用父类的属性或者方法,来扩展子类的功能
9. 多态
9.1. 不同对象调用同一个方法时,显示出不同的效果
9.2. 同一个事件发生在不同的对象上会产生不同的结果
9.3. 多态的基本语法:
9.3.1. 类之间存在继承关系
9.3.2. 将子类的对象指向父类的引用变量
9.4. 向上造型
9.4.1. 将子类的对象指向父类的引用变量
9.4.2. 此时对象的属性是父类的属性,而方法则是子类重写父类的方法
9.5. 编译期类型与运行期类型
9.5.1. Pet p=new Dog()
9.5.2. 等号左边是编译期类型,等号右边是运行期类型
9.5.3. 引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法
9.5.4. 静态绑定发生在编译时期,动态绑定发生在运行时
9.6. 多态参数的应用
9.6.1. 将父类作为方法的传入参数,可以使用instanceof关键字判断编译期类型指向的是哪种具体类型,进行向下造型后,转换为不同的对象,进行不同的操作
10. 抽象类与抽象方法
10.1. 抽象:只声明方法签名,不完成具体实现
10.2. 抽象类的应用场景:设计程序时,无法立即知晓部分方法的具体实现方案,只有关于程序大致功能的概念,建议使用抽象类,将没有确定具体实现的方法设置为抽象方法,因此包含抽象方法的类设置为抽象类
10.3. 关键字abstract
10.4. 抽象类的基本语法
10.4.1. 抽象类不可以直接实例化,只可以用来继承作为其他类的父类存在
10.4.2. 抽象类的派生子类应该提供对其所有抽象方法的具体实现
10.4.3. 如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类,只能用于继承,而不能实例化,但可以有构造函数
10.5. 抽象方法:没有具体实现的方法,起到设计程序的开发规范与约束
11. Final
11.1. Final修饰成员变量,则为常量,只能读取,无法修改
11.2. Final修饰方法,则方法不能被重写
11.3. Final修饰类,则类不能再被继承
12. Static
12.1. 针对一个类所有对象的共性属性,Java采用static成员完成统一调用
12.2. Static修饰的属性会在对象创建之前,被Java虚拟机加载,而且生命周期贯穿整个程序始终
12.3. Static只能修饰成员变量,方法,静态块代码
12.4. 使用类名调用静态数据,例如User.i,User.fun1();
12.5. 静态方法中可以创建对象,但不能给对象的属性赋值或者调用对象的方法
12.6. 实例方法中可以直接调用static方法
12.7. static方法中无法直接调用本类中声明的其他实例方法,如果需要调用,只能在方法体中构建本类的对象,然后利用该对象调用实例方法
12.8. static方法可以直接调用本类中声明的其他static方法
12.9. 实例方法中可以直接访问static成员变量而static方法中不能直接访问非static的成员变量
12.10. 使用static import导入静态类,可以省略静态类名
13. 接口
13.1. 程序设计过程中,无法知晓所有方法的具体实现方案,则使用接口定义所有方法的签名
13.2. 接口与抽象类的区别
13.3. 关键字interface
13.4. 接口可以多继承
13.5. 实现接口的类必须实现接口的所有方法,否则将自身设置为抽象类
14. 枚举
14.1. 枚举的概念:设计任意多个值,提供给外界使用,并且可以扩展每个值的信息
14.2. 枚举语法:
public enum PetColor{
RED,YELLOW,BLUE;
}
14.3. 使用枚举
PetColor.RED
14.4. 自定义枚举,还可以扩展枚举的属性,并封装get,set方法,供外界使用
14.5. 枚举可以有构造方法,为每一个枚举值绑定属性
14.6. 枚举构造方法是私有的
14.7. 枚举值都是final static的,不能通过外界直接修改枚举值,但可以修改枚举的属性
15. 类与类之间的关系
15.1. 关联
15.1.1. 凡是复合xx has-a xx关系可以考虑设计为关联关系,例如人类拥有身份证类的属性
15.1.2. 两元关系:一对一
public class Person{
private IdCard idCard;
}
15.1.3. 多元关系:一对多或者多对一
以员工Employee与公司Company的关系为例:
多元关系一般需要双向设置
在多的方面Employee类设置一的方面Company的属性
public class Employee{
private Company company;
}
在一的方面Company类设置多的方面Employee的数组属性
public class Company{
private Employee[] emps;
}
15.2. 聚合关系:更加紧密的关联关系,例如人类Person和人的家庭Home
public class Person{
private Home home;
}
15.3. 组合关系:整体与部分的关系,部分不能够脱离整体而独立存在
public class Person{
private Heart heart;
}
15.4. 关联,聚合,组合三者在代码的表象上是一致,将一个对象作为另一个对象的属性
15.5. 依赖关系:当某个对象需要实现某个功能时,临时利用另一个对象,则可以设置为依赖关系,符合xx use a xx
public class Person{
//过河的方法,使用到船对象的航行方法
public void crossRiver(Boat boat){
boat.sail();
}
}
public class Boat{
public void sail(){
System.out.println(“船在航行!”);
}
}
16. 内部类
16.1. 在一个类中定义另一个类,也就是将一个类作为另一个类的成员
16.2. 内部类的设计思想是为了彻底实现多重继承
16.3. 如果在不使用接口的前提下,想让一个类实现多个功能,则可以考虑使用内部类
16.4. Java内部类分为成员内部类、局部内部类、匿名内部类、静态内部类
16.5. 成员内部类
// Child类通过继承Father,拥有Father的属性和方法
public class Child extends Father{
private String name;
private int age;
public void show(){}
//定义内部类,让Child类同时也拥有Mother类的属性和方法
//变相地实现了一个类同时继承多个父类
class MotherOfChild extends Mother{
private String name;
private int age;
public void show(){
//如果内部类拥有与外部类同名的属性,
//则直接访问属性名,获取的是内部类的属性
age=17;
name=”jack”;
//如果需要访问外部类的属性,则应该使用外部类名.this.属性名
Child.this.age=18;
Child.this.name=”rose”;
}
}
}
16.5.1. 成员内部类中不能存在任何static的变量和方法
16.5.2. 成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
16.6. 局部内部类
public class Child2{
private int age;
private String name;
public void show(){
class GrandMotherOfChild{
private int age;
private String name;
public void show(){
//访问内部类的属性
age=18;
name=”jack”;
System.out.println(name+”---”+age);
//访问外部类的属性
Child2.this.age=18;
Child2.this.name=”rose”
System.out.println(Child2.this.name+”---”+Child2.this age);
}
}
GrandMotherOfChild gmc=new GrandMotherOfChild();
gmc.show();
}
public static void main(String[] args){
Child2 c2=new Child2();
c2.show();
}
}
16.6.1. 局部内部类可以直接操作外部类的成员变量
16.7. 静态内部类
public class Child3 {
public static void main(String[] args) {
Child3 c3=new Child3();
System.out.println(c3.age+"---"+Child3.name);
c3.fun1();
Child3.fun2();
System.out.println(GrandFatherOfChild.name);
GrandFatherOfChild gfc=new GrandFatherOfChild();
System.out.println(gfc.age);
gfc.fun3();
GrandFatherOfChild.fun4();
}
private int age;
private static String name;
public void fun1() {
//外部类的实例方法访问静态内部类的静态属性
GrandFatherOfChild.name="aaa";
//外部类的实例方法访问静态内部类的实例属性与方法
GrandFatherOfChild gfc=new GrandFatherOfChild();
gfc.age=11;
gfc.fun3();
//外部类的实例方法访问静态内部类的静态方法
GrandFatherOfChild.fun4();
}
public static void fun2() {
//外部类的静态方法访问静态内部类的静态属性
GrandFatherOfChild.name="bbb";
//外部类的静态方法访问静态内部类的实例属性和方法
GrandFatherOfChild gfc=new GrandFatherOfChild();
gfc.age=22;
gfc.fun3();
//外部类的静态方法访问静态内部类的静态方法
GrandFatherOfChild.fun4();
}
//静态内部类
static class GrandFatherOfChild{
private int age;
private static String name;
public void fun3() {
//静态内部类的实例方法访问自己的实例属性
age=17;
name="jack";
System.out.println(age+"---"+name);
//静态内部类的实例方法访问外部类的实例属性
Child3 c3= new Child3();
c3.age=18;
//静态内部类的实例方法访问外部类的静态属性
Child3.name="rose";
System.out.println(c3.age+"---"+Child3.name);
}
public static void fun4() {
//静态内部类的静态方法访问自己的实例属性
GrandFatherOfChild gfc=new GrandFatherOfChild();
gfc.age=11;
//静态内部类的静态方法访问自己的静态属性
name="tom";
System.out.println(name+"---"+gfc.age);
//静态内部类的静态方法访问外部类的实例属性
Child3 c3= new Child3();
c3.age=20;
//静态内部类的静态方法访问外部类的静态属性
Child3.name="jim";
System.out.println(c3.age+"---"+Child3.name);
}
}
}
16.7.1. 它的创建是不需要依赖于外部类的
16.7.2. 它不能使用任何外部类的非static成员变量和方法
16.7.3. 和成员内部类不同,static内部类能够声明static的成员
16.8. 匿名内部类
public class TestAnonymous {
public static void main(String[] args) {
//可以使用匿名内部类创建接口对象
//根据业务,只需要创建一个实现了接口的对象,则可以考虑用匿名内部类
IUsb iu=new IUsb() {
@Override
public void getPower() {
System.out.println("使用匿名内部类实现USB接口");
}
};
iu.getPower();
}
}
interface IUsb{
void getPower();
}
16.8.1. 匿名内部类没有构造方法(匿名内部类没有显式类名)
16.8.2. 匿名内部类要想完成一些初始化工作可以交由类初始化或实例初始化代码块来完成
16.8.3. 匿名内部类对类成员、方法临时变量的访问规则和具备名字的内部类保持一致
17. lambda表达式
17.1. Lambda表达式主要是替换了原有匿名内部类的写法
IUsb iu2=()->System.out.println("使用lambda实现USB接口");
iu2.getPower();
17.2. 如果实现接口的具体语句有多条,则使用{}将所有代码包起来
IUsb iu3=()->{
System.out.println("使用lambda实现USB接口");
System.out.println("使用lambda实现USB接口的第二条语句");
};
iu3.getPower();
17.3. 函数式接口
public interface ITest{
//函数式接口可以有方法体,也就是接口的默认方法
default public void fun1() {
System.out.println("函数式接口可以有方法体");
}
}
public class A implements ITest{
//实现接口的类重写函数式接口的默认方法
public void fun1() {
System.out.println("实现函数式接口的类覆盖默认方法");
}
}
public static void main(String[] args) {
ITest it=new A();
it.fun1();
}
17.3.1. 必须是接口才能使用
17.3.2. 接口中只有一个需要实现的抽象方法
17.4. ::关键字
17.4.1. 主要用作静态方法、成员方法或构造方法的绑定
//定义接口,实现字符串转为整数
public interface ITypeConvertor {
int stringToInt(String st);
}
//定义工具类,实现字符串转为整数,该方法与接口无关
public class MyUtil {
public static int changeStringToInt(String str) {
int i = -1;
Pattern p = Pattern.compile("[0-9]*");
Matcher m = p.matcher(str);
boolean b = m.matches();
if (b) {
i = Integer.valueOf(str);
}
return i;
}
}
public static void main(String[] args){
//使用::关键字将工具类的静态方法作为实现ITypeConvertor接口的方法
ITypeConvertor itc=MyUtil::changeStringToInt;
System.out.println(itc.stringToInt("54325"));
}
18. 异常
18.1. 异常指的是程序运行时发生的不正常事件,可以使用捕获异常的方式来处理
18.2. 错误没法处理,一般虚拟机会选择终止程序运行
18.3. 异常在控制台通常显示为XxxException
18.4. 错误在控制台通常显示为XxxError
18.5. 异常的分类
18.5.1. Throwable
18.5.1.1. Exception
18.5.1.2. Error
18.6. 运行时异常和非运行时异常
18.6.1. 运行时异常: 也称为非检测异常(unchecked Exception), 这些异常在编译期不检测,程序中可以选择处理,也可以不处理。如果不处理运行时会中断,但是编译没问题
18.6.2. 非运行时异常:也称为检测异常(checked Exception), 是必须进行处理的异常,如果不处理,将发生编译期错误
18.6.3. RuntimeException的子类都是运行时异常
18.6.4. NullPointerException-空指针异常
String str=null;
System.out.println(str.length());
18.6.5. ArithmeticException-数学异常
int i=9;int j=0;int k=i/j;
18.6.6. IndexOutOfBoundsException:索引越界异常
int[] nums={1,2,3};
System.out.println(nums[3]);
18.6.7. NumberFormatException-数字格式异常
int i=Integer.valueOf(“abc”);
18.6.8. ClassCastException-类型转换异常
Object obj=new Object();
String s=(String)obj;
18.7. 处理异常的流程
18.7.1. 抛出异常
18.7.2. 捕获异常
18.7.3. 如果捕获成功,异常处理完毕,程序继续运行
18.7.4. 如果捕获失败,异常未被处理,程序中断
18.8. try-catch-finally
//写在程序的任何地方,都表示手动关闭Java虚拟机,程序立刻停止
System.exit(0);
try {
int i=1;
int j=1;
System.out.println(i/j);
}catch (ArithmeticException e) {
System.out.println("除零异常");
//如果捕获正确的异常后,写return语句,finally块仍然被执行,
//但try-catch-finally块之后的代码不会执行
//return;
} catch (Exception e) {
System.out.println("父类异常");
}finally{
System.out.println("程序结束");
//如果在finally块代码最后添加return,则finally块代码仍然执行,
////但try-catch-finally块之后的代码无法达到,编译报错
//return;
}
System.out.println("程序的其他代码");
18.9. throw与throws
18.9.1. 创建了一个异常对象,然后用throw关键字交给异常处理机制去处理
throw new Exception();
18.9.2. 运行时异常是JVM自动抛出,非运行时异常需要程序员用throw关键字抛出
18.9.3. throws用在方法声明处,声明该方法可能发生的异常类型
18.9.4. 在小组协同开发时,根据业务需要,本方法可能出现的异常不在本方法立刻捕获,而是交给该方法的上一层调用者捕获,统一处理
18.9.5. 一个方法如果使用了throws,那么调用该方法时,编译期会提醒必须处理这些异常,否则编译错误
18.10. 自定义异常
18.10.1. 项目组根据业务需求定义业务异常
18.10.2. 多数情况下,继承Exception类;也可以选择继承其他类型异常;
18.10.3. 一般自定义异常类中不写其他方法,只重载必要的构造方法
public class Employee {
private double salary;
public void setSalary(double salary)throws SalaryException{
if(salary>8000){
this.salary=salary;
}else{
//根据业务需求抛出自定义异常,让错误信息在setSalary被调用的程序中显示
throw new SalaryException();
}
}
}
//自定义异常类:显示业务上的错误提示
public class SalaryException extends Exception {
private static final long serialVersionUID = 6425877404468524147L;
public String getMessage() {
return "薪资不能少于8000";
}
}
public static main(String[] args){
try{
Employee emp=new Employee();
emp.setSalary(7000);
}catch(SalaryException e){
System.out.println(e.getMessage());
}
}
19. 断言机制
19.1. 断言用来进行调试,不在生产环境中使用
19.2. eclipse设置断言机制:
19.2.1. preferencesàinstalled jres
19.2.2. 选中右侧本机安装的jre,点击“edit”
19.2.3. 在“default vm arguments”文本框填写-enableassertions
19.2.4. 点击“finish”
19.3. 断言语法
//客户类
public class Customer {
//将两个订单的金额求和
public double addOrder(double d1,double d2){
//如果表达式(d1+d2)==4的结果为真,则不输出"订单求和的公式有误!"
//如果表达式(d1+d2)==4的结果为假,则输出"订单求和的公式有误!"
assert (d1+d2)==4:"订单求和的公式有误!";
return d1+d2;
}
}
20. junit
20.1. junit是用来测试方法的工具包
20.2. eclipse添加Junit工具包
20.2.1. 直接将maven repository网站下载的Junit工具包复制src下
20.2.2. 选中jar包,右键选则“add build path”
20.2.3. 或者选中“项目”,右键“properties”,找到“java build path”,在右侧找到“add library”,选择“Junit”
20.3. Junit基本语法
20.3.1. @Test:将普通方法设置为测试方法,则可以当做main方法来执行
20.3.2. @Before:每次运行任何一个@Test注解的方法之前,都会先执行@Before注解的方法
20.3.3. @After:每次运行任何一个@Test注解的方法之前,都会先执行@Before注解的方法
20.3.4.