2020年java面向对象编程oop课堂笔记

面向对象编程

1. 什么是面向对象

  • 面向过程思想
    • 步骤清晰简单,第一部做什么,第二部做什么…
    • 面向过程适合处理一些较为简单的问题
  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题。

​ 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路去处理。

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

  • 三大特性

    • 封装:
    • 继承
    • 多态

2. 类与对象的创建

一个类由n个属性和n个方法组成

创建与初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
  • 类中的构造器也称为构造方法(分为无参构造有参构造,且无参构造在没有主动创建构造器时,默认存在),是进行创建对象的时候必须调用的。
  • 构造器有以下特点:
    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
    • 构造方法中不能用return返回值,但可以用return作为方法的结束

构造器

  1. 和类名相同,权限修饰符一般只能是public
  2. 没有返回值

作用:

  1. new 本质在调用构造方法
  2. 初始化对象的值

注意点:

  1. 如果没有显式定义任何构造方法,默认调用无参构造
  2. 定义有参构造之后,必须显式地定义无参构造

实例代码

public class Person{

    //无参构造
    private String name;
    private  int age;

    public Person() {
        System.out.println("这是无参构造!");
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("这是有参构造:"+name+"今年"+age+"岁了。");
    }

}

class TestAre{
    public static void main(String[] args) {
        new Person();
        new Person("阿凡",20);
    }
}

3. oop小结

1.类与对象
  类是一个模板:抽象 对象是一个具体的实例
2.方法
   定义与调用
3.对象的引用
   引用类型:对象通过引用来操作
4.属性:也叫成员变量
  默认初始值:
    数字:0 0.0
    char:u0000
    boolean:false
    引用:null
    修饰符 属性类型 属性名 = 属性值!
5.对象的创建和使用
    必须使用new关键字创造对象,构造器
    对象的属性 person.name
    对象的方法 person。sleep()
6.类:
    静态的属性  属性
    动态的行为  方法
    - 封装 继承 多态 -
   

4. 封装

  • 该露的露,该藏的藏

    • 我们程序要追求“ 高内聚,低耦合”。
      1. 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;
      2. 低耦合:仅暴露少量的方法给外部使用。
  • 封装

    • 禁止直接访问某一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐蔽
  • 总言:属性私有,get/set

实例代码

public class Person{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    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 = age;
        }else{
            System.out.println("年龄不合实际");
        }
    }
}

class TestAre{
    public static void main(String[] args) {
        Person person = new Person();
        person.setAge(30);
        System.out.println(person.getAge());
    }
}

5. 继承

  • 关键字extends,所有类默认继承object类
  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
  • java类中只有单继承,没有多继承!即一个类只有一个直接父类
  • 子类继承父类,会自动拥有父类所有public,protected,默认修饰符修饰的属性和方法(不能继承或重写父类的私有成员,构造器,静态方法,final方法)。

实例代码

public class Person  {
    private String name;
    private char sex;
    public void say(String name,char sex){
        System.out.println("我叫"+name+",性别"+sex);
    }

}

class Man extends Person{
    public static void main(String[] args) {
        Man man = new Man();
        man.say("阿凡",'男');
    }
}

6. this和super注意点

this用法:

形式参数可以被认为是局部变量

  1. 用this关键字调用成员变量,防止与局部变量名称冲突
  2. 用this关键字调用该类中其他成员方法(this可以省略)
  3. 用this([参数1,参数2,…])调用该类中的构造方法:
    • 只能在构造方法中使用this调用其他构造方法,不能在成员方法中使用
    • 在构造方法中使用this调用其他构造方法的语句只能写在第一句
    • 不能在一个类的两个构造方法中使用this互调

super用法:

  1. 使用super来调用父类的成员变量和方法,构造方法

super.成员变量

super.成员方法

super([参数1,参数2,…])

  1. 通过super调用父类构造方法的语句只能出现在子类构造方法的第一行,并且只能出现一次

super VS this:

  • 代表的对象不同:
  • this:本身调用这个对象
  • super:代表父类对象的应用
  • 前提:
    • this:没有继承也可以使用
    • super:只能在继承条件才可以使用
  • 构造方法
    • this():本类的构造
    • super():父类的构造

注意:

  1. 在构造方法中,this与super不能同时出现

  2. static静态方法中不能使用this和super

  3. super可以调用父类的静态方法

实例代码

//person类
public class Person  {
    private String name = "person";

    public void print(){
        System.out.println("阿凡person");
    }
}
//student类  继承  person类
class Student extends Person{
    private String name = "阿凡student";
    public void test1(){
        print();  //阿凡student
        test();   //阿凡person
        super.print();  //阿凡person
    }
    public void test(){
        System.out.println(name);   //阿凡student
        super.print();    //阿凡person
    }
    public void print(){
        System.out.println(this.name);
    }
}
//测试类
class TestAre{
    public static void main(String[] args) {
        new Student().test();
        new Student().test1();
    }
}

7. 重写

重写:需要有继承关系,子类重写父类的方法!

  1. 方法名、参数列表、返回值类型必须相同
  2. 子类重写父类方法时,不能使用比父类被重写的方法更严格的访问权限

修饰符访问权限大小:public>protected>default>private

  1. 抛出的异常:范围可以被缩小,但不能扩大:

classNotFoundException(小) -->Exception(大)

为什么需要重写:

  1. 父类的功能,子类不一定需要,或者不一定满足!
  2. Alt + Insert : @override
//person类
public class Person  {
  private String name = "阿凡公民";
  public void print(){
      System.out.println(name+"去上班!!");
  }
}


//student类 继承与 person类
class Student extends Person{
  private String name = "阿凡同学";
  @Override
  public void print(){  //重写print方法
      System.out.println(name+"去上学!!");
  }
}

class TestAre{
    public static void main(String[] args) {
        new Student().print();  //阿凡同学去上学!!
    }
}

8. 多态

定义:不同类的对象在调用同一方法时所呈现出的多种不同行为。

优点:提高了程序的可拓展性和可维护性。

  • 多态一般在接口被实现或类被继承时使用

  • 对象的类型转换:

    • 父类引用子类对象时**(向上转型),不能通过父类变量去调用子类特有方法**
    • 将父类引用对象强制转换为子类时**(向下转型)**,尽量用instanceof判断一个对象是否是某个类(或接口)的实例或子类对象。

    对象 instanceof 类(或接口)

instanceof 用来测试一个对象是否为一个类的实例
boolean result = obj instanceof class
注意点:
  1. obj必须为引用类型,不能为基本类型
  2. obj可以为null
  3. obj可以为class类的直接或间接子类
  4. obj可以为class接口的实现类

实例代码

//Person类
public abstract class Person {
    public abstract void work();
}
//老师类继承Person类
class Teacher extends Person{
    @Override
    public void work() {
        System.out.println("老师上课");
    }
    //老师特有方法
    public void write(){
        System.out.println("老师写教案");
    }
}
//医生类继承Person类
class Doctor extends Person{
    @Override
    public void work() {
        System.out.println("医生看病");
    }
    //医生特有方法
    public void operation(){
        System.out.println("医生做手术");
    }
}
//测试类
class Test{
    public static void main(String[] args) {
        Person p1 = new Teacher();
        Person p2 = new Doctor();
        p1.work();  //老师上课
        p2.work();  //医生看病
        if( p1 instanceof Teacher){  //判断p1是否是Teacher类的对象
            Teacher teacher = (Teacher)p1;
            teacher.write(); //老师写教案
        }
        else{
            Doctor doctor = (Doctor)p2;
            doctor.operation();
        }
    }
}

9. final关键字

final关键字可以修饰类、变量、方法:

  1. final修饰的类不能被继承

  2. final修饰的方法不能被子类重写

  3. final修饰的变量(成员变量局部变量)是常量,只能被赋值一次

    注意:

    成员变量被final修饰时,声明变量的同时必须初始化赋值

    局部变量被final修饰时,可以先声明,再赋值一次

10. static关键字

static用于修饰类的属性,方法,代码块等,称为静态Xxx

static只能修饰成员变量,不能修饰局部变量

注意点:

  • 静态变量(也叫全局变量)可以被该类的所有实例对象共享

类名.变量名

  • 在同一类中,成员方法可以直接调用静态方法,但是静态方法不能直接调用成员方法,必须创建对象后才能访问成员方法

类名.静态方法();

或者

实例对象名.静态方法();

  • 静态代码块在类第一次被new 对象 实例化后才会被执行,且只会执行一次,一般用来加载初始化信息。

static{

}

**static和final同时使用 **

  1. static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!

  2. 对于变量,表示一旦给值就不可修改,并且通过类名可以访问。

  3. 对于方法,表示不可覆盖,并且可以通过类名直接访问。

实例代码

class Student{
    private  static int age;
    private double score;

    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println(Student.age);
        System.out.println(s1.age);
        System.out.println(s1.score);
    }
}

静态代码块

实例代码

public class Person {
    //赋初始值
    {
        System.out.println("匿名代码块");
    }
    //只执行一次
    static{
        System.out.println("静态代码块");
    }

    public Person(){
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        new Person();
    }

}

11. 抽象类

  • 关键字:abstract 抽象类,属于类 单继承 (接口是多继承)
  • abstract修饰的抽象方法只有方法名字,没有方法的实现!
  • 注意点
    • 抽象类中的成员变量定义没有要求
    • 包含抽象方法的类必须定义为抽象类
    • 抽象类不能new出来,只能靠子类实现
    • 抽象类中可以写普通方法,包括静态方法
    • 抽象方法必须写在抽象类中,但抽象类可以没有抽象方法

12. 接口

接口:只有规范,比抽象类更严格,是抽象类的特殊形式

public interface 接口名{

}

作用

  1. 接口里面定义的成员变量都是 public static final修饰,只能是常量,必须赋初始值
  2. 接口中的成员方法只能是抽象方法。默认修饰符 public abstract,但public abstract可以省略不写。
  3. 注意:接口不可以有构造方法,但抽象类可以
  4. 接口不能实例化,接口中没有构造方法,其他类使用implements 可以实现多个接口,
  5. 必须要重写接口中的所有方法
  6. 接口中的成员方法权限只能且都是public
  7. 接口是多继承

实例代码

public interface Animal {
    void shout(String name);
}

class Cat implements Animal{

    @Override
    public void shout(String name) {
        System.out.println(name + "在喵喵叫!");
    }
}

class Dog implements Animal{
    @Override
    public void shout(String name) {
        System.out.println(name+"在汪汪叫!");
    }
}

class AnimalTest{
    public static void main(String[] args) {
        Animal a1 = new Cat();
        Animal a2 = new Dog();
        a1.shout("猫");
        a2.shout("狗");
    }
}

13. 4种内部类

非常重要内部类不能有静态方法或属性。

成员内部类

外部类名 对象名 = new 外部类名();

外部类名.内部类名 变量名 = new 外部类名().内部类名();

注意:

  • 在成员内部类中,内部类可以直接(不用new 外部类创建对象)调用外部类的所有属性+方法(包括静态和非静态)。
  • 在外部类中,不可以直接调用内部类中的属性+方法,但可以创建内部类对象后调用。

实例代码

//person类  外部类
public class Person {
    
    String name = "Afan";
    int age = 20;
    
    public void doSomething(){
        System.out.println("AFan在吃饭!");
    }
    public void say(){
        Heart heart = new Heart();
        heart.fleed();
        System.out.println("AFan说你好!");
    }

    //心脏 成员内部类
    class Heart{
        
        public void jump(){
            System.out.println("心脏跳动!!");
            doSomething();//直接调用外部类方法
            say();
        }
        public void fleed(){
            System.out.println("血在流");
        }
    }
}

class Test{
    public static void main(String[] args) {
        Person person = new Person();
        Person.Heart heart = person.new Heart();
        heart.jump();
        heart.fleed();
    }
}

局部内部类

也叫方法内部类,在方法中定义,有效范围只限于方法内部,等同于局部变量。

注意:

  • 局部内部类可以在new 外部类对象后调用外部类的属性+方法
  • 局部内部类可以 直接调用 自身在外部类中所在方法里的局部变量。
  • 只有在创建局部内部类的方法中才可以创建局部内部类的对象,并调用内部类的所有属性+方法。

实例代码

/person类
public class Person {
    String name = "Afan";
    int age = 20;
    
    public void doSomething(){
        System.out.println("AFan在吃饭!");
    }
    public void say(){
        System.out.println("AFan说你好!");
    }

    public void produce(){
        
        String product_name = "电脑";
        //产品类 局部内部类
        class Production{
           // String product_name = "电脑";
            public void use(){
                Person person = new Person();  //外部类对象
                person.doSomething();
                System.out.println(product_name+"的使用");
            }
        }
        Production production = new Production();
        production.use();
    }
}

class Test{
    public static void main(String[] args) {
        Person person = new Person();
        person.produce();

    }
}

静态内部类

本质:使用static关键字修饰的成员内部类

  • 静态内部类只能直接调用外部类中的静态属性和静态方法
  • 其他类需要调用静态内部类的属性和方法时,可以跳过外部类,直接new 内部类对象来访问其成员。

外部类名.静态内部类名 对象名 = new 外部类名.静态内部类名();

实例代码

//person类
public class Person {
    static String name = "Afan";

    public static void doSomething(){
        System.out.println("AFan在吃饭!");
    }
    public void say(){
        System.out.println("AFan说你好!");
    }

    //心脏类 就在成员内部类前面加个static
    static class Heart{

        public  void jump(){
            doSomething();

           // Person person = new Person(); 访问非静态成员必须创建对象。
            //person.say();

            System.out.println(name+"的心脏在跳动!!");
        }
    }
}
class Test{
    public static void main(String[] args) {
        Person.Heart heart = new Person.Heart();
        heart.jump();
    }
}

匿名内部类

java类调用某个方法时,如果该方法的参数类型是接口类型,那么除了传递一个接口的实现类,也可以使用匿名内部类实现该接口来作为该方法的参数。(开发中常用)

[修饰符] 方法名(new 父类名或者接口名(){
    // 方法重写
    @Override 
    public void method() {
        // 执行语句
    }
};)

实例代码

//接口类
public interface Animal {
    void shout(String name);
}

class AnimalTest{
    String name;
    public void animalShout(Animal animal){
        animal.shout(name);
    }
    public static void main(String[] args) {

      AnimalTest a1 = new AnimalTest();
      a1.name = "猫";
      //匿名内部类
      a1.animalShout(new Animal() {
          @Override
          public void shout(String name) {
              System.out.println(name+"在叫!!!");
          }
      });
    }
}

JDK8的Lamabda表达式

使用条件:只适用于在匿名内部类中只有一个抽象方法的接口实现,简化代码。

([数据类型1 变量名1,数据类型2 变量名2,…]) ->{表达式主体}

注意点:

  1. 参数列表只有一个参数时可以省略”()“和变量的数据类型
  2. 表达式主体只有一条语句时,可以省略主体的大括号
  3. 表达式主体可以有return返回值,当只有一条return语句,可以省略return

实例代码

//接口类
public interface Animal {
    void shout(String name);
}
class AnimalTest{
    String name;
    public void animalShout(Animal animal){
        animal.shout(name);
    }
    public static void main(String[] args) {

      AnimalTest a1 = new AnimalTest();
      a1.name = "小猫";
      //Lamabda表达式
      a1.animalShout(name ->
              System.out.println(name+"在叫!!!")
      );
    }
}

进一步简化Lamabda表达式(了解)

使用条件:Lamabda表达式主体只有一条语句

用法:程序省略主体的大括号,用英文双冒号“::”来引用方法和构造器

Lamabda表达式对普通方法和构造方法的引用形式

种类 对应的引用示例
类名引用普通方法 类名::类普通方法名
类名引用静态方法 类名::类静态方法名
对象名引用方法 对象名::实例方法名
构造器引用 类名::new

14. 异常

定义:程序在编译、运行过程中出现的非正常状况

  java的异常类都继承于java.lang.Throwable类

Throwable的继承体系

2020年java面向对象编程oop课堂笔记_第1张图片

  • Error类:错误类,比较严重(了解)
  • Exception类:异常类,程序本身可以处理,java开发中进行的异常处理都是针对Exception类及其子类

Throwable类常用方法

方法说明 功能描述
String getMessage() 返回此throwable的详细消息字符串
void printStackTrace() 打印完整的异常信息

处理异常的两种方式

  1. 使用try…catch语句对异常进行捕获处理

    try{
      //可能发生异常的语句
    }catch(Exception类或其子类 e){
       e.printStackTrace(); //打印输出异常原因
       //对捕获的异常做相应处理
    }finally{
       //无论程序是否异常都必须执行的语句
    }
    

    实例代码

    public class Example {
        public static void main(String[] args) {
           int result = divide(4,0);
           if(result == -1){
               System.out.println("程序出现异常");}
            else{
               System.out.println(result);   
           }
        }
        //运行结果:出现的异常:/ by zero
        //        无论程序是否异常都必须执行的finally语句
        //        程序出现异常
        
        //除法运算
        public static int divide(int a,int b){
            try{
                int result = a/b;
                return  result;
            }catch(Exception e){
                System.out.println("出现的异常:"+e.getMessage());
            }finally{
                System.out.println("无论程序是否异常都必须执行的finally语句");
            }
            return -1; //如果程序异常,返回-1
        }
    }
  2. 使用throws抛出异常,等以后再处理有可能的异常,

    [修饰符] 返回值类型 方法名([参数列表]) throws Exception{
       //方法体
       }
    

    有可能出现异常的方法加上throws关键字后,其他类调用它时首先要处理完异常之后才能使用该方法。

实例代码

public class Example {
    public static void main(String[] args) {

       try {
           int result = divide(4, 0);
           System.out.println(result);
       }catch(Exception e){
           System.out.println("出现异常:"+e.getMessage());
       }

    }
    //运行结果:出现异常:/ by zero

    //除法运算
    public static int divide(int a,int b) throws Exception{
        int result = a/b;
        return result;
    }
}

你可能感兴趣的:(java)