Java面向对象

124 阅读3分钟

什么是面向对象

  • 面向对象编程(oop)的本质就是: 以类的方式组织代码,以对象的形式封装数据
  • 从认识论角度考虑是先有对象后有类。对象是具体的事物。类是抽象的,是对对象的抽象。
  • 从代码运行角度考虑是先有类后有对象,类是对象的模板

创建与初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建时,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

    1. 必须和类名相同
    2. 必须没有返回类型,也不能写void
  package com.oop.Demo01;
  public class Person {
      //一个类即使什么也不写,他也会存在一个方法
      String name;
      //构造器:1.和类名相同
      //        2.没有返回值
      //1.使用new关键字,本质是在调用构造器
      //2.用来初始化值
      //无参构造
      public Person(){
          
      }
      //有参构造:一旦定义了有参构造,无参构造必须显示定义
      public Person(String name){
          this.name=name;
      }
  }
  
  package com.oop.Demo01;
  public class Application {
      public static void main(String[] args) {
          //new 实例化了一个对象
          Person person = new Person("ding");
          System.out.println(person.name);
      }
  }

封装

  • 封装(数据的隐藏):通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏(高内聚,低耦合)。
  • 记住这句话就够了:属性私有,get/set

get/set作用方法

  package com.oop.Demo03;
  //类 private:私有
  public class Student {
      //属性私有
      private String name;//名字
      private int age;//年龄
      private char sex;//性别
      //提供一些可以操作这个属性的方法!
      //提供一些public的get set方法
      //get 获得这个数据
      public String getName(){
          return this.name;
      }
      //set 给这个数据设置值
      public void setName(String name){
          this.name=name;
      }
      public int getAge() {
          return age;
      }
      public void setAge(int age) {
          if (age>120||age<0){//不合法年龄
              this.age=3;
          }
          else {
              this.age = age;
          }
      }
  }
  
  package com.oop.Demo03;
  public class Application {
      public static void main(String[] args) {
          Student student = new Student();
          student.setName("九九香");
          System.out.println(student.getName());//九九香
          student.setAge(200);
          System.out.println(student.getAge());//3
      }
  }

封装的作用

  1. 提高程序的安全性,保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统的可维护性增加了

继承

继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,用关键字:extends表示。

object类

  
  package com.oop.Demo04;
  //在Java中所有的类,都默认直接或者间接继承object
  //Person 人 父类
  public class Person {
      private int money=10_0000_0000;
      public void say(){
          System.out.println("说了一句话!");
      }
      public int getMoney(){
          return this.money;
      }
      public void setMoney(int money){
          this.money=money;
      }
  }
  
  package com.oop.Demo04;
  //Student is 人
  public class Student extends Person {
  }
  
  package com.oop;
  import com.oop.Demo04.Student;
  public class Application {
      public static void main(String[] args) {
          Student student = new Student();
          student.say();
          student.setMoney(10_0000_0000);
          System.out.println(student.getMoney());
      }
  }

Super

注意点:

  1. super调用父类的构造方法,且必须在构造方法的第一个
  2. super必须只能出现在子类的方法或者构造方法中
  3. super和this不能同时调用构造方法!
  
  package com.oop.Demo05;
  public class Student extends Person {
      public Student() {//无参构造器
          //隐藏代码:调用了父类的无参构造
          super();//调用父类的构造器,必须要在子类构造器的第一行
          System.out.println("Student无参执行了");
      }
      private String name="Studentname";
      public void print(){
          System.out.println("Student执行中");
      }
      public void test1(){
          print();
          this.print();
          super.print();
      }
      public void test(String name){
          System.out.println(name);
          System.out.println(this.name);
          System.out.println(super.name);//输出父类的name
      }
  }
  
  package com.oop.Demo05;
  public class Person {
      public Person() {
          System.out.println("Person无参构造执行了");
      }
      public Person(String name) {
          this.name = name;
      }
      protected String name="Personname";
      //私有的东西无法被继承
      public void print(){
          System.out.println("Person执行中");
      }
  }
  package com.oop;
  import com.oop.Demo05.Person;
  import com.oop.Demo05.Student;
  ​
  public class Application {
      public static void main(String[] args) {
          Student student = new Student();
          //student.test("传入的name");
          //student.test1();
      }
  }

方法重写

需要有继承关系,子类重写父类的方法!子类的方法和父类一致;方法体不同

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大但不能缩小:public > Protected > Default > private
  4. 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException--->Exception(大)

为什么要重写?

  1. 父类的功能,子类不一定满足,或者不一定满足

Alt + Insert: override;

  
  package com.oop.Demo06;
  public class A extends B{
      @Override //注解:有功能的注释
      public void test() {
          //super.test();
          System.out.println("A=>test()");
      }
      /*
      public void test(){
          System.out.println("A=>test");
      }*/
  }
  
  package com.oop.Demo06;
  public class B {
      public void test(){
          System.out.println("B=>test()");
      }
  }
  
  package com.oop;
  import com.oop.Demo06.A;
  import com.oop.Demo06.B;
  public class Application {
      //静态方法和非静态的方法区别很大
      //静态方法://方法的调用只和左边,定义的数据类型有关
      //非静态方法:重写
      public static void main(String[] args) {
          A a = new A();
          a.test();//A=>test()
          //父类的引用指向了子类
          B b = new A();//子类重写了父类的方法
          b.test();//A=>test()
      }
  }

多态

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式

  • 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)

  • 多态存在的条件:

    1. 有继承关系
    2. 子类重写父类方法
    3. 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性

  • instanceof (类型转换)引用类型

  
  package com.oop.Demo07;
  public class Person {
      public void run(){
          System.out.println("run");
      }
  }
  
  package com.oop.Demo07;
  public class Student extends Person {
      @Override
      public void run() {
          System.out.println("son");
      }
      public void eat(){
          System.out.println("eat");
      }
  }
  
  package com.oop;
  import com.oop.Demo07.Person;
  import com.oop.Demo07.Student;
  public class Application {
      public static void main(String[] args) {
          //一个对象的实际类型是确定的
          //new Student();
          //new Person();
  ​
          //可以指向的引用类型就不确定了:父类的引用指向子类
          //Student 能调用的方法都是自己的或者继承父类的!
          Student s1 = new Student();
          //Person 父类型,可以指向子类,但是不能 调用子类独有的方法
          Person s2 = new Student();
          Object s3 = new Student();
  ​
          //可以执行哪些方法,主要看对象左边的类型,和右边关系不大!
          s2.run();//子类重写了父类的方法,执行子类的方法
          s1.run();
          s1.eat();
          ((Student)s2).eat();
      }
  }

\