UM2L8——面向对象

本章代码关键字

1
2
3
4
5
6
7
8
9
class                //类的声明关键字
finalize() { } //在对象成为垃圾后,开始GC时,如果对象存在finalize()方法,会先执行一次该方法,下次GC才会回收该方法
extends //类的继承关键字
instanceof //判断某个对象是否是某个类型,类似于C#的is关键字
final //此关键字修饰的类不能再被继承,修饰的方法不能再被重写,修饰的变量不能修改(等同于常量)
super //调用父类的方法的关键字
abstract //抽象类和抽象方法关键字
interface //接口声明关键字
implements //类继承接口关键字

面向对象

面向对象回顾

概念:万物皆对象
用程序来抽象(形容)对象,用面向对象的思想来编程

面向对象三大特性是封装、继承、多态

注意:
面向对象是一种编程范式,面向对象编程语言的编程思想和使用几乎是一致的
使用C#中的面向对象编程思想去写Java即可,Java中也是通过class类去封装对象的

Java中类的封装(声明)

Java中类的封装规则和C#基本一致
相对C#来说还少了不少功能,使用起来更加 (残废) 简单

要注意,对于公开的枚举或者类来说,它们必须要单独一个代码文件编写而不能在同一个文件内声明

Java中的类声明和使用和C#中基本一模一样,声明格式是:

1
2
3
4
5
6
7
8
class 类名
{
特征——成员变量
行为——成员方法
构造函数 //和C#一样,默认会有一个无参的构造函数,如果声明了新的构造函数,原有的默认无参构造函数就会被顶替掉
finalize函数 //作用类似于析构函数,但不是析构函数
静态函数
}

注意!Java中没有C#中的:

  1. 成员属性(有类似自动生成的get​、set​方法)
  2. 析构函数(有类似的finalize​函数,当对象变成垃圾,然后GC时会调用该函数,但不会回收对象,直到下一次垃圾回收时,才会回收该对象)
  3. 索引器
  4. 运算符重载

Java类的声明的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Person {
//静态成员
//静态变量
public static int testStatic = 1;
//静态方法
public static void test() {
System.out.println(testStatic);
}

// 成员变量
public String name = "唐老狮";
private String secret = "秘密";
private int age = 18;

public Person girlFriend;
public Person[] boyFriend;

public E_Sex sex = E_Sex.Man;

//构造函数
//如果声明了有参构造函数,则默认的无参构造函数将不可用,
//如果想要保留,需要自己实现
public Person() { }

public Person(String name) {
this.name = name;
}

//finalize函数
//当对象变成垃圾,然后GC时会先调用该函数,然后该垃圾将不被回收
//直到下一次垃圾回收时,才会回收该对象
protected void finalize() {
System.out.println("回收");
}

//成员方法
public void Speak(String str) {
System.out.println(str);
}

public enum E_Sex {
Man,
Woman,
}
}

finalize方法

Java的finalize()​方法,需要使用protect​修饰符,是在对象成为垃圾后,开始GC时,
如果对象存在finalize()​方法,会先执行一次该方法,本次垃圾回收会先不回收此对象
直到下一次垃圾回收时,才会回收该对象

1
2
3
4
5
6
7
8
public class Person {
//finalize函数
//当对象变成垃圾,然后GC时会先调用该函数,然后该垃圾将不被回收
//直到下一次垃圾回收时,才会回收该对象
protected void finalize() {
System.out.println("回收");
}
}
1
2
3
4
5
6
7
public class Lesson9 {
public static void main(String[] args) {
Person p = new Person();
p = null;
System.gc();
}
}

输出:

1
回收

IDEA的自动生成类似属性的方法

IDEA提供了对成员变量自动生成类似于C#属性的方法的选项,
对要生成属性的变量按下右键,点击生成,选择getter​和setter​即可

imageimage

然后IDEA就会为我们自动生成方法

1
2
3
4
5
6
7
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
private String secret = "秘密";

值得一提的是,它本质就是方法,和C#的属性有本质的区别

Java中类的继承

Java中继承使用和C#基本一致,只是有一些关键字和小规则不同而已

Java的继承和C#的相同点如下:

  1. 类与类之间只能单继承
  2. 万物之父都是Object
  3. 遵循里氏替换原则(可以父类装子类对象)

Java中继承的写法如下,需要加上extends​,而不是:

1
public class Father { }
1
public class Son extends Father { }

万物之父Object中的关键方法

  1. getClass()​:类似C#中的getType()

    下面的逻辑就可以输出对象的类名

    1
    2
    3
    4
    5
    6
    public class Lesson10 {
    public static void main(String[] args) {
    Father f = new Father();
    System.out.println(f.getClass());
    }
    }

    输出:

    1
    class Father
  2. toString()​:将对象以字符串形式返回

    1
    2
    Father f = new Father();
    System.out.println(f.toString());

    输出:

    1
    Father@4eec7777
  3. equals()​:比较两个对象的内部内容,而==​是判断引用地址是否相等(或者说判断变量是否指向一个对象)

    我们可以自己重写equals()​方法来自定义两个对象的比较方法

    1
    2
    3
    4
    5
    6
    public class Father {
    @Override
    public boolean equals(Object obj) {
    return super.equals(obj);
    }
    }

父子类的上下转换(里氏替换原则)

  1. 子类自动向上转换

    1
    Father f2 = new Son();
  2. 父类强制向下转换(括号强转)

    1
    Son s = (Son) f2;

instanceof

用于判断对象类型,类似C#中的is​关键字

1
2
3
4
5
6
7
8
if (f2 instanceof Father) {
System.out.println("是Father类");
}

if (f2 instanceof Son) {
Son s2 = (Son) f2;
System.out.println("是Son类");
}

输出:

1
2
是Father类
是Son类

final

类似C#中的密封关键字sealed

  • 让变量无法被修改(变成常量)
  • 让函数无法被重写
  • 让类无法被继承

Java中类的多态

Java中多态相关知识点和C#中基本一致,相对C#更简单

  1. 没有vo关键字,有类似b的super
  2. 继承接口用implements
  3. 接口中可以声明变量,但是是静态常量
  4. 不存在显示实现接口(多个接口存在同名方法,实现一次即可)

Java中的vob

Java中没有vo关键字,也就是virtual(虚函数)和override(重写)
我们如果要重写基类的方法,直接在子类中实现同名方法即可,它会直接覆盖父类方法!!
Java中有类似 base​ 的关键字 super

注意:重写是Java会自动补全一个@Override​,它类似于注释,可有可无,主要是用来帮助我们阅读代码

java重写的写法如下:

1
2
3
4
5
public class Father {
public void Eat() {
System.out.println("父亲吃东西");
}
}
1
2
3
4
5
6
7
public class Son extends Father {
@Override
public void Eat() {
super.Eat();
System.out.println("儿子吃东西");
}
}
1
2
3
4
5
6
public class Lesson11 {
public static void main(String[] args) {
Father s = new Son();
s.Eat();
}
}

输出:

1
2
父亲吃东西
儿子吃东西

抽象类和抽象方法

Java中的抽象类和抽象方法使用和C#中基本一致
关键字:abstract
抽象类不能被实例化,抽象方法在抽象类中声明,必须被实现

1
2
3
4
public abstract class Animal {
public int age;
public abstract void Eat();
}

接口

  1. Java中接口中方法默认(只能)为public
  2. Java中接口可以声明字段,但是默认(只能)是static​和final​的,也就是静态常量
  3. Java中继承接口的关键字是implements​,一般写在继承类之后
  4. 继承多个接口用逗号分隔
  5. Java中不存在显式实现接口,重写不同接口的同名方式时,“两个接口共享”
1
2
3
4
public interface IFly {
int speed = 10; //默认只能是static final的
void Fly(); //默认是public的
}
1
2
3
public interface IBird {
void Fly();
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Son extends Father implements IFly, IBird {
@Override
public void Eat() {
super.Eat();
System.out.println("儿子吃东西");
}

@Override
public void Fly() {
System.out.println("飞行");
}
}
1
2
3
4
5
6
7
8
9
public class Lesson11 {
public static void main(String[] args) {
System.out.println(IFly.speed);
IFly s2 = new Son();
s2.Fly();
IBird s3 = (IBird) s2;
s3.Fly();
}
}

输出:

1
2
3
10
飞行
飞行