Day 005 20210218-20210221
面向对象和异常处理太绕了,之后或许得回看。不过好在内容不多。
面向对象OOP(Object-Oriented Programming)
类与对象
- 类:一种抽象得数据类型,如:动物、猫、狗。。。
- 对象:抽象概念的具体实例,如:甲、乙、丙。。。
使用new创建对象。
构造器
- 名字与类名相同。
- 无返回值、返回值类型,但同时也没有"void"。
- 分为无参构造器与有参构造器。
- 无参构造器默认定义。但当存在有参构造器时必须定义无参构造器。
无参构造器
public class Demo01{
public Demo01(){
// 语句
}
}
有参构造器
public class Demo01{
public Demo01(int a, String name){
// 语句
}
}
快捷键
alt + insert,即(fn + alt + delete)。选择constructor。
三大特性
- 封装
- 继承
- 多态
封装
高内聚,低耦合。
属性私有,get/set。
public class Demo02{
private int a;
private String name;
private double b;
public int getA(){
return this.a;
}
public void setA(int a){
this.a = a;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public double getB(){
return this.b;
}
public void setB(double b){
this.b = b;
}
}
import Demo02;
public class Test{
public static void main(String[] args){
Demo02 demo02 = new Demo02();
// System.out.println("demo02.a"); // 报错。
System.out.println(demo02.getA()); // 0
demo02.setA(1);
System.out.println(demo02.getA()); // 1
}
}
封装有利于程序的安全性。
继承
java只有单继承,没有多继承,但有多重继承。
子类"is a"父类,猫是动物,狗是动物,人是动物。
继承,依赖,组合,聚合。
子类继承父类的除private外全部方法和属性。
子类extends父类
public class Animal{
}
public class Dog extends Animal{
}
Object类
Object类是所有类的父类。
super
// 父类:
public class Parent{
protected String name = "cat01";
}
// 子类:
public class Son extends Parent{
private String name = "cat02";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name); // super访问父类属性
}
}
// 试验类
import Son;
public class Test{
public static void main(String[] args){
Son son = new Son("cat03");
son.test();
/*
cat03
cat02
cat01
*/
}
}
在无参构造器中,子类的无参构造器默认首行super();语句调用父类属性和方法。
super();位于无参构造器内部语句的第一行;
this();位于无参构造器内部语句的第一行;
因此,一个无参构造器中无法同时含有super();语句和this();语句。
方法重写
子类继承父类方法,但如果子类方法和父类方法内容不同,在父类的引用指向子类时,子类重写了父类的方法,执行子类的方法。
Father father = new Child();
代码:
public class Animal{
public int weight;
public int age;
public void shout(){
System.out.println("shout");
}
}
public class Cat extends Animal{
public void shout(){
System.out.println("Meow!");
}
public void roll(){
System.out.println("roll");
}
}
import Animal;
import Cat;
public class Test{
public static void main(String[] args){
Animal animal = new Cat();
animal.shout(); // Meow!
//animal.roll(); // 报错!
}
}
原因分析:
Animal x = new Cat();
我有许多动物(Animal类型)。
现在创建一个名为x的动物(x动物),且它本身是一只猫(Cat类型)。
但是我不知道x动物是一只猫,我只知道x动物是一只动物。
动物都会shout,但是只有猫会roll。
我想要看我创建的x动物到底会什么。
于是我只能让x动物shout,而不能让x动物roll。
而这个x动物本身是一只猫。
所以x动物shout结果为Meow!,x动物没有roll。
故输出Meow!。
修饰符范围:
// public > protected > default(不写修饰符时默认为default) >private
多态
一个父类方法因为多个子类的重写而展现出多样性。
instanceof关键词
规则
Father a = new Son();
如果
类B是Father类直接或间接的一个子类(包括相同类);
Son类是类B直接或间接的一个子类(包括相同类),则
a instanceof B == true; // 黑猫是猫吗? true
如果
类B是Father类直接或间接的一个子类(包括相同类);
Son类不是类B直接或间接的一个子类(包括相同类),则
a instanceof B == false; // 黄狗是猫吗? false
如果
类B不是Father类直接或间接的一个子类(包括相同类),则
// a instanceof B 报错 // 玫瑰花是猫吗? 报错
示例
import Parent;
import Son1;
public class Test{
Object obj = new Son1();
System.out.println(obj instanceof Son1); // true
System.out.println(obj instanceof Son2); // false
System.out.println(obj instanceof Parent); // true
System.out.println(obj instanceof Object); // true
System.out.println(obj instanceof String); // false
Parent parent = new Son1();
System.out.println(parent instanceof Son1); // true
System.out.println(parent instanceof Son2); // false
System.out.println(parent instanceof Parent); // true
System.out.println(parent instanceof Object); // true
System.out.println(parent instanceof String); // 报错
}
类型转换
- 由子类至父类直接转换,但会丢失子类独有的方法;
Parent parent = new Son(); // 子类有独有的方法son();
// parent.son(); 报错
- 由父类至子类强制转换,但会丢失精度。
((Son) parent).son();
static关键词
静态类,静态方法,静态代码块,静态导入包。。。
{
// 匿名代码块
System.out.print(1);
}
static {
// 静态代码块 最早加载,只加载一次。
System.out.print(2);
}
public Animal{
// 构造方法
System.out.print(3);
}
public static void main(String[] args){
Animal animal1 = new Animal(); // 213
Animal animal2 = new Animal(); // 13
}
抽象类
abstract修饰符
无方法语句。
不能被"new"。
子类继承:
- 重写抽象方法,子类不是抽象类。
- 不重写抽象方法,子类必须还是抽象类。
抽象类可以没有抽象方法,但是有抽象方法的类一定要是抽象类。
public abstract class Father{ // 抽象类
public abstract void test(); // 抽象方法
}
public class Son{
@Override
public void test(){
System.out.println("Test");
}
}
import Son;
public class Test{
public static void main(String[] args){
Son son = new Son();
son.test(); // Test
}
}
接口
interface关键词
接口方法均为抽象方法
implements连接
创建接口
public interface Animal{
void shout();
}
public interface Master{
void roll();
}
类连接接口
可以连接多个接口,实现多继承。
需要重写接口中的方法
public class Cat implements Animal, Master{
@Override // 快捷键fn + alt + insert
public void shout(){
System.out.println("Meow!");
}
@Override
public void roll(){
System.out.println("roll~roll~~");
}
}
运行主程序
import Cat;
public class Test{
public static void main(String[] args){
Cat cat = new Cat();
cat.shout(); // Meow!
cat.roll(); // roll~roll~~
}
}
内部类
成员内部类
静态内部类
局部内部类
匿名内部类
new Cat().shout(); // Meow!
new Cat().roll(); // roll~roll~~
异常和错误
三大种类
检查性异常
程序员无法预见,如:
用户输入导致异常(1/0 = ?),文件路径异常。
运行时异常
程序员可以避免,如:
public int a(){
return b();
}
public int b(){
return a();
}
错误Error
无法在程序中检测到,常导致程序崩溃。如:
栈溢出。
抛出和捕获异常
try, catch, finally, throw, throws关键词
快捷键:选中想要用try监控的语句ctrl + alt + T,选择。
catch
在catch的过程中,只会执行最先符合的那一个,因此要把范围较小的放在前面,范围较大的放在后面,而范围最大的Throwable则放在最后(如果有Throwable的话)。
public class Test{
public void cal(){
System.out.println(a/b);
}
public static void main(String[] args){
int a = 1;
int b = 0;
try{ // try监控的范围
new Test().cal();
}catch (Error e){
System.out.println("变量b不能为零。");
}catch (Exception e){
// 语句
}catch (Throwable t){
// 语句
}finally{ // 结束语句,可不写。
System.out.println("finally");
}
}
}
throw
主动抛出异常,在上一级捕捉。
public class Test{
public void test(int a, int b) throws ArithmeticException{ // 此处为throws
if(b == 0){
throw ArithmeticException(); // 此处为throw
}
}
public static void main(String[] args){
try{
new Test().test(1,0);
}catch (ArithmeticException e){
e.printStackTrace(); // 打印异常情况
}
}
}
自定义异常
Tips
- 快捷键fn + alt + insert;
- 快捷键ctrl + alt + T;