Java基础(四)--面向对象

1.包

其实包就是文件夹和golang中的包一样,就是php中的命名空间

  • 命名 com.公司名.项目名.业务模块名

    2.权限控制

  • public:对外公开的

  • protected:对子类和同一个包中的类公开

  • 没有修饰符:向同一个包的类公开

  • private:只有类本身可以访问,不对外公开

    • 只有public和默认可以修饰类,别的不可以

3.封装、继承、多态

继承

+ 父类叫基类或者超集
+ 子类叫派生类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person {
public String name;
protected int age;

public void setAge(int age) {
this.age = age;
}

public int getAge() {
return age;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Stutent extends Person{
private int score;

public Stutent(String name,int age,int score) {
this.name = name;
this.age = age;
this.score = score;
}

public void setScore(int score) {
this.score = score;
}

public int getScore() {
return score;
}

public void show(){
System.out.println("学生信息"+this.getName()+" "+this.getAge() +" "+this.getScore());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Teacher extends Person{
private double solary;

public Teacher(String name,int age,double solary) {
this.solary = solary;
this.age = age;
this.name = name;
}

public void setSolary(double solary) {
this.solary = solary;
}

public double getSolary() {
return solary;
}

public void show(){
System.out.println("输出老师信息"+this.name+" "+this.age+" "+this.solary);
}
}
  • 细节
    • 子类不能直接访问父类的私有方法和属性
    • 创建子类对象时默认会调用父类的构造器,且默认调用父类的无参构造器,除非使用super(参数列表)指定调用哪个构造器
    • super()this() 不能同时在一个构造器中使用
    • java所有的类都是Object类的子类

Super

  • 访问父类的方法、属性、构造器 但是private的不能访问
  • 当子类中有和父类重名的方法、属性、构造器时使用 super调用父类的,若果没有重name使用super和使用this效果一样

方法重写(override)

  • 子类覆盖父类的方法
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
public class Hello {
public static void main(String[] args) {
Cat cat = new Cat();
cat.cry();
}
}

class Animal{
public void cry(){
System.out.println("动物发出叫声");
}

public Object m1(){
return null;
}
}

class Cat extends Animal{
@Override
public void cry() {
System.out.println("喵喵喵");
}

@Override
public String m1() {
return "hello";
}
}
  • 注意事项

    • 子类方法的形参列表和方法名必须和父类被覆盖的形参列表和方法名一样
    • 子类返回类型和父类方法的返回类型一致或者子类方法返回类型是父类方法返回类型的子类,都满足重写的规则,例如方法 m1()
    • 子类方法不能缩小父类方法的访问权限,但是允许扩大访问权限
  • 注意区分重载(overload)和 重写 (override)

多态

  • 规则
    • 一个对象的编译类型和运行类型可以是不一致的
    • 编译类型在定义对象时,就确定了且不能改变
    • 运行类型是可以改变的
    • 编译类型看定义的 = 号左边,运行类型看 = 号的右边
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
public class Hello {
public static void main(String[] args) {

Animal animal = new Animal();

Animal cat = new Cat();
animal.play(cat);

Dog d = new Dog();
animal.play(d);
}
}

class Animal{
public void cry(){
System.out.println("动物发出叫声");
}

public void play(Animal a){
a.cry();
}
}

class Cat extends Animal{
@Override
public void cry() {
System.out.println("喵喵喵");
}

}

class Dog extends Animal{
@Override
public void cry() {
System.out.println("汪汪汪");
}
}
  • 向上转型
    1. 本质:父类的引用指向了子类的对象
    2. 语法 父类类型 引用名 = new 子类类型();
    3. 特点:可以调用父类中所有成员(须遵循访问权限),不能调用子类中特有的成员

作用就是使用子类重写的方式实现多态,重载子类重载的方法都不能被调用

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
public class Hello {
public static void main(String[] args) {

Animal cat = new Cat();

// 不能调用子类特有的成员
// cat.catshow();
}
}

class Animal{
public void cry(){
System.out.println("动物发出叫声");
}

}

class Cat extends Animal{
@Override
public void cry() {
System.out.println("喵喵喵");
}

public void catshow(){
System.out.println("cat show...");
}
}
  • 向下转型

    1. 语法:子类类型 引用名 = (子类类型) 父类引用;
    2. 只能强转父类的引用,不能强转父类的对象
    3. 要求父类的引用必须指向的是当前目标类型的对象
    4. 可以调用子类类型中的所有的成员
      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
      public class Hello {
      public static void main(String[] args) {

      // 错误的转换,不能将对象强转
      // Animal animal = new Animal();
      // Cat cat = (Cat) animal;
      // cat.catshow();

      Animal ani = new Cat();
      Cat cat = (Cat) ani;
      cat.catshow();

      }
      }

      class Animal{
      public void cry(){
      System.out.println("动物发出叫声");
      }

      public void play(Animal a){
      a.cry();
      }
      }

      class Cat extends Animal{
      @Override
      public void cry() {
      System.out.println("喵喵喵");
      }

      public void catshow(){
      System.out.println("cat show...");
      }
      }
  • 属性的注意项

  1. 属性的最终值在编译期确定好的,和方法的调用时在运行时确定,不一样
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Hello {
    public static void main(String[] args) {
    Father f = new Son();
    System.out.println(f.name); // 爸爸
    }
    }

    class Father {
    String name = "爸爸";
    }

    class Son extends Father{
    String name = "儿子";
    }
  2. instanceof 判断的是运行类型
  • 动态绑定
  1. 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
    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
    public class Hello {
    public static void main(String[] args) {
    A a = new B();
    System.out.println(a.sum()); // 30
    }
    }

    class A {
    public int i = 10;
    public int sum(){
    return getI() + 10;
    }

    public int sum1(){
    return i + 10;
    }
    public int getI(){
    return i;
    }
    }

    class B extends A{
    public int i = 20;
    // public int sum(){
    // return i + 20;
    // }
    public int getI(){
    return i;
    }
    public int sum1(){
    return i + 10;
    }

    }
  • 应用
    • 多态数组
    • 多态参数
      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
      47
      48
      49
      50
      51
      52
      53
      54
      public class Hello {
      public static void main(String[] args) {
      Sellers seller = new Sellers();
      seller.soldMethod(new FreeTicket());
      seller.soldMethod(new SoldTicket());

      seller.sold(new FreeTicket());
      seller.sold(new SoldTicket());
      }
      }

      class Sellers {
      public String name = "售票员小美";
      public void soldMethod(Ticket t){
      System.out.println(name + "-卖出一张-" + t.getTicketName());
      }

      //另一种写法
      public void sold(Ticket t){
      if (t instanceof FreeTicket){
      System.out.println(name + "-卖出一张-" + ((FreeTicket) t).name);
      }

      if (t instanceof SoldTicket){
      System.out.println(name + "-卖出一张-" + ((SoldTicket) t).name);
      }
      }
      }

      class Ticket{
      public String name;

      public String getTicketName(){
      return name;
      }
      }

      class FreeTicket extends Ticket{
      public String name = "免费票";

      @Override
      public String getTicketName() {
      return name;
      }
      }

      class SoldTicket extends Ticket{
      public String name = "收费票";

      @Override
      public String getTicketName() {
      return name;
      }
      }