学习08[面向对象]

面向对象OOP

什么是面向对象

  • 面向过程

    线性思维,步骤明确

  • 面向对象

    • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统

    • 但是具体到微观操作,仍需要面向过程的思路去处理

  • OOP

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

  • 抽象

  • 三大特性

    • 封装

    • 继承

    • 多态

  • 认识论角度:先有对象后有类

    对象是具体的事物,类是抽象的,是对对象的抽象

  • 代码运行角度:先有类后有对象,

    类是对象的模板

 

回顾方法并加深

  • 方法的定义

    • 修饰符

    • 返回类型

      //Demo01   类  用class修饰
      public class Demo01 {}
      /*
      修饰符 返回值类型 方法名(){
         //方法体
         return 返回值;
         }
      * */
      public String sayHello(){    return "Hello,world!";
      }


      public int max(int a ,int b){
      return a>b?a:b;//三元运算符
      }
    • break和return的区别

      1. break跳出switch,结束循环

      2. return结束方法,返回一个结果

    • 方法名——规范+见名知意

    • 参数列表

      1. 参数类型

      2. 参数名

      3. 任意参数数量...

    • 异常抛出

  • 方法的调用

     

    • 静态方法和非静态方法

      //静态方法 static
      //非静态方法 没有static
      1. 静态方法之间引用

      2. 非静态方法需要实质化

      public void say(){
      System.out.println("学生说话了");
        }

      //非静态方法 实例化这个类 new
      //对象类型 对象名 = 对象值
      //new.Student()
      Student student = new Student();
      student.say();

       

    • 方法之间的调用

      a方法不可以引用b方法的原因:

      a是静态

      b是非静态

      1626698215308

     

    • 形参和实参

      public static void main(String[] args) {    
      //形式参数和实际参数的类型要对应    
      int add =Demo03.add(1,2);    System.out.println(add);
      }
      public static  int add(int a,int b){    
         return a+b;
      }

     

    • 值传递和引用传递

      1. 值传递

        两个结果都是1

      //值传递
      public static void main(String[] args) {    
         int a=1;    System.out.println(a);//1  
         Demo04.change(a);    System.out.println(a);//1
      }

      //返回值为空
      public static  void change(int a){      
         a = 10;
      }
      1. 引用传递

      1626700253591

      public class Demo05 {    
         //引用传递:对象 本质还是值传递    
         public static void main(String[] args) {        
      Person person = newPerson();        
      System.out.println(person.name);//null        
             Demo05.change(person);      System.out.println(person.name);//秦疆    
         
        }    
         public static  void change(Person person){       //person是一个对象,指向-->Person person = new Person();这是一个具体的对象,可以改变属性        
         person.name= "秦疆";    
        }
      }



      //定义了一个Person类,里面有一个属性:name
      class Person{    
         String name;//默认值为null
      }

 

类和对象的关系

  • 类是抽象的数据类型,对某一类事物整体描述或定义

  • 对象是抽象概念的具体实例

 

创建和初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建的时候,除了分配内存空间以外,还会给创建好的对象进行默认的初始化(null/0)

1626749351236

  • 一个项目应该只存在一个main方法

    //类:抽象的,需要实例化
    //类实例化后会返回一个自己的对象
    //student对象就是一个Student类的具体实例
    Student xiaoming = new Student();
    
  • 类里面包括属性和方法

  • 构造器

    类中的构造器也称构造方法

    1. 必须和类的名字相同

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

    //一个类即使什么都不写,它也会存在一个方法
    //显示的定义构造器
    public Person(){    
    }
    
  • 构造器的作用

    1. 用来初始化值

    2. 使用new关键字,本质是在调用构造器

//有参构造:一旦定义了有参构造,无参构造就必须显示定义
public Person(String name){    this.name=name;
}
  • 定义有参构造后,如果想使用无参构造,就要显示的定义一个无参构造

  • alt+insert创建构造器

    • 有参构造

      右键——Generate——Constructor

    • 无参构造

      右键——Generate——Constructor——选择select none

      1626751946457

 

创建对象内存分析

1626780674318

 

小结

  • 类与对象

    类是一个模板,抽象,对象是一个具体的实例

  • 方法

    定义,调用

  • 对象的引用

    • 引用类型:八个基本类型

      对象是通过引用来操作,栈引用堆

  • 属性:字段Field,成员变量

    • 默认初始化

      数字:0 0.0

      char:u0000

      boolean:false

      引用:null

    • 修饰符 属性类型 属性名 = 属性值

  • 对象的创建和使用

    • new

    • 构造器 Person kuangshen = new Person( );

    • 对象的属性kuangshen.name

    • 对象的方法kuangshen.sleep( )

    • 静态的属性 属性

    • 动态的行为 方法

 

封装

  • 高内聚

    类的内部数据操作细节自己完成,不允许外部干涉

  • 低耦合

    仅暴露少量的方法给外部使用

  • 数据的隐藏(信息隐藏)

    通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问

  • 属性私有,get/set

  • 意义

    1. 提高程序的安全性,保护数据

    2. 隐藏代码的实现细节

    3. 统一接口

    4. 提高系统的可维护性

//private:私有 无法直接引用
private String name;//名字


//提供一些可以操作这些属性的方法


//提供一些public的get,set方法
//get获得这个数据
public String getName(){
        return this.name;
}
//给这个数据赋值
public void setName(String name){
        this.name=name;
}

//s1.getName().sout可以直接生成
//System.out.println(s1.getName());
//alt+insert:自动生成get和set
//右键——Generate——Constructor——Getter and Setter
public String getName() {
                return name;
        }

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

 

继承

  • 继承的本质是对某一批类的抽象

  • extends的意思是"扩展",子类是父类的扩展

  • 继承是类和类的关系

  • 一个为子类,一个为父类

  • 子类继承父类,使用关键字extends来表示

  • 在java中默认直接或者间接继承object

  • ctrl+h:打开关系树?

    1626790690488

  • Java中只有单继承,没有多继承

    一个父亲可以有多个儿子,一个儿子不能有多个父亲

 

Super

  • //父类
    public Person() {    System.out.println("Person无参执行了");
    }
    
    //子类
    //隐藏代码:默认调用父类的无参构造
    //super();
    public Student() {    System.out.println("Student无参执行了");
    }
    

    1626829428387

  • 注意点:

    1. Super调用父类的构造方法,必须在构造方法的第一个

      1626829649229

      1626829606733

    2. Super必须只能出现在子类的方法或者构造方法中

    3. Super和this不能同时调用构造方法

      1626829853587

      1626829923579

  • vs this

    1. 代表对象不同

      • this:本身调用者这个对象

      • Super:代表父类对象的应用

      1626828447702

    2. 前提不同

      • this:没有继承也可以使用

      • Super:只有在继承条件下才可以使用

    3. 构造方法不同

      • this();本类的构造

      • super();父类的构造

  • 父类没有无参构造,子类也无法写无参构造

 

方法重写

  • 重写都是方法的重写,和属性无关

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

    1. 方法名必须相同

    2. 参数列表必须相同

    3. 修饰符:范围可以扩大,但不能缩小

      public>protected>default>private

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

  • 子类和父类的方法必须一致,方法体可以不同

  • 为什么需要重写?

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

  • O代表重载

1626831140761

  • Override重写

    @Override//有功能的注释

  • 自动生成重写快捷键:

    右键——Generate——Constructor——选择

    1626831598864

    1626831719616

//静态方法和非静态方法区别很大
//静态static:方法的调用只和左边,即定义的数据类型有关
//非静态:重写,结果一样——>A  A
public static void main(String[] args) {    
    A a = new A();    
    a.test();//A    
    B b = new A();//子类重写了父类的方法    
    b.test();//B
}

 

多态

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

  • 动态编译:类型

//一个对象的实际类型是确定的
//new Student();
//new Person();


//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();


s2.run();//子类重写父类的方法,执行子类的方法
s1.run();
  • 让可扩展性更强

  • 注意事项:

    1. 多态是方法的多态,属性没有多态

    2. 父类和子类,有联系,类型转换异常

      ClassCastException

    3. 存在条件:

      ①继承关系

      ②方法需要重写,子类重写父类方法

      其中不能重写,无法实现多态的:

      • static方法,属于类,不属于实例

      • final常量

      • private方法

      ③父类引用指向子类对象

      子类重写父类的方法,则执行子类的方法 father f1= new son( );

  • 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大

//Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person 父类型,可以指向父类,但不能调用子类独有的方法
Person s2 = new Student();

 

instanceof

  • 判断一个对象时什么类型

  • 能不能编译通过:是否存在父子关系

System.out.println(x instanceof y)
//Object > String
//Object > Person > Teacher
//Object > Person > StudentObject 

object = new Student();

System.out.println(object
instanceof  Student);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
  • 父类引用指向子类对象

    Person person=student;
    
  • 把子类转化为父类,向上转型

    把父类转化为子类,向下转型,强制转换

  • 类型之间的转化 父 子

//高-----------------低
Person obj = new Student();

//低到高直接转化,高到低强制转化
//想用子类方法可以强转化为子类
//student将这个类型转为Student类型,我们就可以使用Student类型的方法了 

Student student = (Student) obj; 
student.go();
//最后两句可以简化为
((Student) obj).go();
  • 子类转化为父类,可能丢失自己本来的一些方法

    1626957815210

 

static

  • 变量

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);
}
  • 方法

1626961748323

  • 静态代码块

1626960721476

1626960979324

  1. 静态代码块只执行一次

    匿名代码块赋初始值

1626960915054

1626961019305

  • 静态导入包

import static java.lang.Math.random;
  • 通过final被修饰的类没有子类

public final class Person {

1626961527754

 

抽象类

  • abstract修饰抽象类

//abstract抽象类
public abstract class Action {    
    //约束,有人帮我们实现    
    //abstract 抽象方法 只有方法名字,没有方法的实现    
    public abstract void doSomething();
}
//抽象类的所有方法,必须由继承它的子类实现,除非继承它的子类也是抽象的
public class A extends Action{    
    @Override    
    public void doSomething() {    
    }
}
  • Java的类是单继承,但是接口可以实现多继承

  • 抽线类特点

    1. 不能new这个对象,只能靠子类去实现它:约束

      1626964612182

    2. 抽象类里面可以写普通方法,抽象方法必须再抽象类里

  • 抽象的抽象

 

接口

  • 普通类:只有具体实现

  • 抽象类:具体实现和规范(抽象方法)都有

  • 接口:只有规范,自己无法写方法,约束和实现分离

  • 接口就是规范,定义一组规则:如果你是汽车,则必须能跑

  • 接口的本质是契约

1627007952407

1627009298064

  • 利用接口实现多继承

    public class UserServiceImpl implements UserService,TimeService{
        
    }
    
  • 接口里面定义的属性都是常量

    public static final 
    
    int age=99;
    
  • 作用:

    1. 约束

    2. 定义一些方法,让不同的人实现

    3. 方法都是public abstract

    4. 常量public static final

    5. 接口不能被实例化,接口中没有构造方法

    6. implements可以实现多个接口

    7. 必须要重写接口中的方法

 

N种内部类

  • 外部类和内部类

1627011676156

//new 外部对象
Outer outer = new Outer();

//通过这个外部类来实例化内部类
//outer.new Inner();
Outer.Inner inner = outer.new Inner();
inner.getId();
  • //一个Java文件中可以有多个class类,但是只能有一个public class类
    class A{    
    }
    
  • 局部内部类

    1627012148543

  • 匿名内部化

    public class Test {    
       public static void main(String[] args) {        
           //匿名内部化:        
           //没有名字初始化,不用将实例保存在变量中:Apple apple = new Apple();        
           new Apple().eat();    
      }
    }
    class Apple{    
       public void eat(){    
      }
    }
posted @ 2021-07-23 12:00  qwertyuiopxuexi  阅读(67)  评论(0)    收藏  举报