Day06 面向对象

1.初识面向对象

  • 面向对象思想:物以类聚,分类的思维模式,首先对方法进行分类,然后对每个分类进行面向过程的思索。

  • 面向对象编程(OOP)的本质:以类的方式组织代码,以对象的组织封装数据

  • 三大特性:

    • 封装
    • 继承
    • 多态
  • 类:对具体事物的共同点的抽象,比如张三李四都是人,人便是一个类,Person类;

  • 对象:具体的实例,比如张三就是人的一个具体实例,张三家里的狗旺财就是狗的一个具体实例

2.方法回顾和加深

  • 见Day04

3.对象的创建分析

  • 创建对象:new;例如:new 类名(); 类名 对象名 = new 类名();

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

    //学生类
    public class Student {
    //    属性:字段
        String name; //null
        int age; //0
    
    //    方法
        public void study(){
            System.out.println(this.name + "在学习");
        }
    }
    
    //一个项目应该只存在一个main方法
    public class Application {
        public static void main(String[] args) {
    //        类:抽象的,需要实例化
    //        类实例化后返回一个自己的对象
    //        student对象就是一个Student类的具体实例!即类会生小孩(对象)
            Student xiaoming = new Student();
            Student xiaohong = new Student();
    
            xiaoming.name = "小明";
            xiaoming.age = 11;
            xiaohong.name = "小红";
    
            System.out.println(xiaoming.name); //小明
            System.out.println(xiaoming.age); //11
            xiaoming.study(); //小明在学习
    
            System.out.println(xiaohong.name); //小红
            System.out.println(xiaohong.age); //0
        }
    }
    
  • 构造器

    • 一个类即使什么都不写,也会存在一个方法,即无参构造器

在这里插入图片描述

  • 必须和类的名字相同

  • 必须没有返回类型,也不能写void

  • alt + insert 可自动生成构造器()

  • this.某某,指的是当前类的参数;=后面,指的是参数传进来的值

  • public class Person {
        String name;
    
    //    使用new关键字,本质是在调用构造器,
    //    无参构造器作用:
        /*
        1.初始值对象的值
        * */
        public Person(){
            name = "石佩";
        }
    
    //    有参构造器;注意:一旦定义了有参构造,无参构造必须显示定义
        public Person(String name){
            this.name = name;
        }
    
    }
    

4.类与对象小结

1.类与对象
    类是一个模板,抽象的;对象是一个具体的实例
2.类:
    静态的属性--属性
    动态的行为--方法
3.属性:字段Field 成员变量
    定义格式:修饰符 属性类型 属性名 = 属性值;
    默认初始化:
        数字:0  0.0
        char:u0000
        boolean:false
        引用:null
4.方法
    定义,调用!
5.对象的引用
    引用类型:对象 & 数组
    对象是通过引用来操作的:栈--->堆(地址)
6.对象的创建和使用
    定义格式: Person person = new Person;
    必须使用new关键字创造对象,new的本质:调用构造器
    对象的属性 person.name
    对象的方法 person.sleep();

5.面向对象三大特性

  • 封装

    • 该露的露,该藏的藏。设计程序追求“高类聚,低耦合”

    • 属性私有,get/set

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

在这里插入图片描述

  • //类 private:私有
    public class Student {
        //属性私有
        private String name;
        private int age;
        private char sex;
    
        //属性私有了,其他类不能再通过Student实例化使用这些属性了
    }
    
  • 例子:

    //类 private:私有
    public class Student {
        //属性私有
        private String name;
        private int age;
        private char sex;
    
        //属性私有了,其他类不能再通过Student实例化使用这些属性了
        //故提供一些可以操作这些属性的方法
        //提供一些public的get、set方法
    
        //get:可以让其他类获得这个数据
        public String getName() {
            return this.name;
        }
        
        //set:给这个数据设置值
        public void setName(String name) {
            this.name = name;
        }
    }
    
    public class Application {
        public static void main(String[] args) {
            Student sp = new Student();
    
            sp.setName("石佩");
            System.out.println(sp.getName()); // 打印结果 石佩
        }
    }
    
  • alt – insert --Getter and Setter 可以自动生成get和set方法

  • 继承

    • extend,类跟类之间的关系

    • 特点:子类可以继承分类所有的public方法、属性

      //Person 人:父类
      public class Person {
          public void say(){
              System.out.println("说了一句话");
          }
      
          public void money(){
              System.out.println("10亿");
          }
          
          private void cerete(){
              System.out.println("打牌");
          }
      }
      

在这里插入图片描述

  • 在java中所有的类都继承Object类

  • super

    例子:

    //Person 人:父类
    public class Person {
        protected String name = "shipei";
    }
    
    //Student is 人
    public class Student extends Person{
        private String name = "penny";
        public void test(String name){
            System.out.println(name); //石佩
            System.out.println(this.name); //penny
            System.out.println(super.name); //shipei
        }
    }
    
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
    
            student.test("石佩");
        }
    }
    
    • super笔记

      super注意点:
          1.继承了父类的子类会默认调用一个super();
          如果父类写了一个有参的构造器,必须再显示的加一个无参的构造器,否则子类会报错。(见下图)
          2.super调用父类的构造方法,必须处于子类构造方法的前面
          3.super必须只能出现在子类的方法或构造方法中
          4.super和this 不能同时调用构造方法(即super();和this();不可同时使用)
      
      super VS this:
          1.代表的对象不同:
              this: 本类对象的引用
              super:代表父类对象的引用
          2.前提:
              this:没有继承也可以使用
              super:只能在继承条件下才可以使用
          3.构造方法:
              this(); 本类构造
              super(); 父类构造
      

在这里插入图片描述
在这里插入图片描述

修正:

在这里插入图片描述

  • 方法重写

    • 静态方法不能重写

      public class B {
          public static void test(){
              System.out.println("B-->test()");
          }
      }
      
      public class A extends B{
          public static void test(){
              System.out.println("A-->test()");
          }
      }
      
      public class Application {
          public static void main(String[] args) {
      
              //静态方法的调用只和左边的定义的类型有关
              // 与右边的new的对象无关
              A a = new A();
              a.test(); //A-->test()
      
              //父类的引用指向了子类
              B b = new A();
              b.test(); //B-->test()
          }
      }
      
    • 非静态方法可以重写

      override表示重写,下图带有字母O的蓝底色图形,为重载的标志

在这里插入图片描述
在这里插入图片描述

  ```java
  public class B {
      public void test(){
          System.out.println("B-->test()");
      }
  }
  ```

  ```java
  public class A extends B{
      @Override //注解:有功能的注释,表示重写
      public void test() {
          System.out.println("A-->test()");
      }
  }
  ```

  ```java
  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()
      }
  }
  ```

  - 重写小结:

    ```bash
    重写注意点:
        1.前提:
            需要继承关系,子类重写父类的方法
            方法名必须相同
            参数列表必须相同
            修饰符范围,子类的 >= 父类的;Public > Protected > Default > Private
            抛出的异常范围,子类的 <= 父类的;ClassNotFoundException < Exception
        2.使用:
            Alt + Insert --> 点击override
        3.非静态方法才可重写
    
    重写与重载的区别:
        1.定义区别:
            ①重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同,
            调用的时候根据函数的参数来区别不同的函数。
            ②重写(也叫覆盖)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现,
            即函数名和参数都一样,只是函数的实现体不一样。
        2.类的关系区别:
            重写是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。
        3.产生方法区别:
            重写只能由一个方法或只能由一对方法产生关系;重载是多个方法之间的关系。
        4.参数列表要求区别
            重写要求参数列表相同;重载要求参数列表不同。
        5.调用方法区别
            重写关系中,调用方法体是根据对象的类型来决定;
            重载关系是根据调用时的实参表与形参表来选择方法体的。
    ```
  • 多态

    • 父类引用指向子类对象,这种特点,允许不同类的对象对同一方法作出响应

      例如下面三句话,引用类型不同但指向同一个子类对象。

      		Student s1 = new Student();
              Person s2 = new Student(); //父类的引用(父类对象)指向子类对象
              Object s3 = new Student();
      
    • 功能:实现动态编译,程序可扩展性增强

    • 例子:

      public class Person {
          public void run(){
              System.out.println("run");
          }
      }
      
      public class Student extends Person{
          @Override
          public void run() {
              System.out.println("son");
          }
      
          public void eat(){
              System.out.println("eat");
          }
      }
      
      public class Application {
          public static void main(String[] args) {
              //一个对象的实际类型是确定的
              //new Student();
              //new Person();
      
              //但可以指向的引用类型就不确定了
              Student s1 = new Student();
              Person s2 = new Student(); //父类的引用指向子类对象
              Object s3 = new Student();
      
              s1.eat(); //eat
              s1.run(); //son
              s2.eat(); //报错 对象执行哪些方法,主要由对象左边的类型决定;Person父类型,可以指向子类,但不能调用子类自己写的方法
              s2.run(); //son 子类重写了父类的方法,尽管s2为Person的引用但执行的是子类重写的方法
          }
      }
      
    • 多态小结

      多态注意点:
          1.多态是方法的多态,属性没有多态
          2.父类和子类,有联系  类型转换异常(ClassCastException)
          3.存在条件:
              1)继承关系;
              2)方法需要重写;
                  这些方法不可被重写:
                      -static方法,属于类,它不属于实例
                      -final修饰的方法,处于常量池
                      -private修饰的方法
              3)父类的引用指向子类对象 Father f1 = new Son();
      
    • instanceof和类型转换

      • instanceof:用于判断一个对象与另一个对象是否存在继承关系,这样就可以知道这个对象是什么类型;是则返回true,否则返回false

        public class Person {
            public void run(){
                System.out.println("run");
            }
        }
        
        public class Student extends Person{
            public void walk(){
                System.out.println("walk");
            }
        }
        
        public class Teacher extends Person{
        }
        
        public class Application {
            public static void main(String[] args) {
                //Object > Person > Student
                //Object > Person > Teacher
                //Object > String
                Object object = new Student();
        
                System.out.println(object instanceof Object); //true
                System.out.println(object instanceof Person); //true
                System.out.println(object instanceof Student); //true
                System.out.println(object instanceof Teacher); //false
                System.out.println(object instanceof String); //false
        
                System.out.println("===========");
        
                Person person = new Student();
        
                System.out.println(person instanceof Object); //true
                System.out.println(person instanceof Person); //true
                System.out.println(person instanceof Student); //true
                System.out.println(person instanceof Teacher); //false
                //System.out.println(person instanceof String); //编译报错,Person和String没有关系,他们之间不能进行比较和转化
                System.out.println("===========");
                
                Student student = new Student();
        
                System.out.println(student instanceof Object); //true
                System.out.println(student instanceof Person); //true
                System.out.println(student instanceof Student); //true
                //System.out.println(student instanceof Teacher); //编译报错,Student和Teacher没有关系
                //System.out.println(student instanceof String); //编译报错,Student和String没有关系
                
            }
        }
        
      • 类型转换:把父类转换为子类,由高向低转,强制转换;把子类转换为父类,由低向高转,直接转换

        public class Application {
            public static void main(String[] args) {
                //类型之间的转换  父    子
                Person person = new Student();
                Student student = (Student) person; //高到低,强制转换
                student.walk();
        
                Student student1 = new Student(); 
                Person person1 = student1; //低到高,直接转换
        
        //子类中由walk方法,Person类中没有walk方法,Person类型的引用需要调用walk方法可将其类型强制转化为Student类型
        变为:((Student) person).walk();
        

在这里插入图片描述

  • 补充static

    //static方法和属性的特点
    public class Student {
        //属性
        private static int age; //静态变量   多线程!
        private double score; //非静态变量
    
        //方法
        public static void go(){
        }
        
        public void run(){
            go();
        };
        
        public static void main(String[] args) {
            Student s1 = new Student();
    
            //静态属性既可以用对象调用,也可以直接通过类名调用
            System.out.println(Student.age); 
            //System.out.println(Student.score); //编译报错
            System.out.println(s1.age);
            System.out.println(s1.score);
            
            //静态方法既可以用对象调用,也可以用类名调用,也可以直接用;
            // 非静态方法可以直接使用静态方法
            Student.go();
            go();
            s1.go();
            s1.run();
            //run(); //编译出错
        }
    }
    
    //静态代码块
    public class Person {
        //2.
        {
            //代码块(匿名代码块),,可用于赋初值
            System.out.println("匿名代码块");
        }
    
        //1. 只执行一次
        static{
            //静态代码块
            System.out.println("静态代码块");
        }
    
        //3.
        public Person(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            new Person();
            System.out.println("============");
            new Person();
        }
    }
    

在这里插入图片描述

//静态导入包
package com.oop.demo07;
//静态导入包
import static java.lang.Math.random;
/**
 * @Author:Sp
 * @Date:2021/1/21
 * @Description:com.oop.demo07
 */
public class Test {
    public static void main(String[] args) {
        // 不导入静态包,应该写Math.random()
        //导入静态包,可直接写random()
        System.out.println(random());
    }
}

6.抽象类和接口

  • 抽象类:用abstract修饰的类

    • 特点:
      1. 抽象类不能new,即不能实例化,只能靠子类去实现它。抽象类中有构造方发
      2. 抽象类中可以写普通方法
      3. 抽象方法必须再抽象类中

    • 类A继承类Action,必须要实现Action类中的抽象方法

在这里插入图片描述

```java
//abstract 抽象类
public abstract class Action {
    //抽象方法:只有方法名字,没有方法实现!
    public abstract void doSomething();

    //特点:不能new,只能靠new子类去实现它
}
```

```java
//继承了抽象类的子类,必须要实现抽象类的方法,除非子类也是抽象类
public class A extends Action{
    @Override
    public void doSomething() {

    }
}
```
  • 接口:用interface修饰的类

    • 特点:
      1. 比抽象类(具体方法和抽象方法都有)还抽象,只有方法的声明,自己无法写方法
      2. extends只能单继承,利用接口可以实现多个接口
      3. 继承了接口的类必须重写接口中的方法
      4. 接口不能不能被实例化,接口中没有构造方法

    • 例子:

      //interface定义接口
      public interface UserService {
          //常量~public static final
          int AGE = 99;
          
          //接口中的所有定义的方法都是抽象的public abstract
          void add(String name);
          void delete(String name);
          void update(String name);
          void query(String name);
      }
      
      public interface TimeService {
      }
      
      //实现了接口的类,必须重写接口中的方法
          //利用接口可实现多继承
      public class UserServiceImpl implements UserService, TimeService{
          @Override
          public void add(String name) {
      
          }
      
          @Override
          public void delete(String name) {
      
          }
      
          @Override
          public void update(String name) {
      
          }
      
          @Override
          public void query(String name) {
      
          }
      }
      

7.内部类及OPP实战

  • 内部类:一个类的内部定义了另一个类。比如,A类中定义了一个B类,那么B类相对于A类来说就称为内部类,A类相对于B类来说是外部类

    • 成员内部类

      • 可以获得外部类的私有属性
      • 可以使用外部类的方法
      //Outer为外部类
      public class Outer {
          private int id;
          public void out(){
              System.out.println("这是外部类的方法");
          }
          public class Inner{
              public void in(){
                  System.out.println("这是内部类的方法");
              }
              public void getID(){
                  System.out.println(id);
              }
              public void fun(){
                  out();
              }
          }
      }
      
      
      public class Application {
          public static void main(String[] args) {
              // new
              Outer outer = new Outer();
              outer.out(); // 这是外部类的方法
      
              //通过外部类来实例化内部类
              Outer.Inner inner = new Outer().new Inner();
              //或
              Outer.Inner inner1 = outer.new Inner();
      
              inner.in(); // 这是内部类的方法
              inner.getID(); // 0
              inner.fun(); // 这是外部类的方法
          }
      }
      
    • 静态内部类

      public class Outer {
          private static int id;
          public void out(){
              System.out.println("这是外部类的方法");
          }
          public static class Inner{
              public void in(){
                  System.out.println("这是内部类的方法");
              }
              public void getID() {
                  System.out.println(id);
              }
          }
      }
      
    • 局部内部类:在方法里面定义一个类

      public class Outer {
          //局部内部类
          public void method(){
              class Inner{
                  //方法、属性
              }
          }
      }
      
    • 匿名内部类

      public class Test {
          public static void main(String[] args) {
              //正常情况下
              Apple apple = new Apple();
              apple.eat();
      
              //匿名内部类:没有名字而去初始化类, 不用将实例保存到变量中
              new Apple().eat();
      
              new UserService(){
                  @Override
                  public void hello() {
                      System.out.println("Hello World!");
                  }
              }.hello();
      
          }
      }
      
      class Apple{
          public void eat(){
              System.out.println("Eat Apple.");
          }
      }
      
      interface UserService{
          void hello();
      }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值