11.面向对象编程OOP

面向对象

面向过程与面向对象

  • 面向过程:线性
  • 面向对象:分类,协作

不可分割

面向对象

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

  • 核心思想:抽象

  • 三大特性:继承、封装、多态

回顾方法

方法定义

package com.oop;

import java.io.IOException;

//Demo1   类
public class Demo1 {

    //main方法
    public static void main(String[] args) {

    }

    /*
    修饰符 返回类型 方法名(....){
            方法体
            return 返回值;
    }
     */
    //return 结束方法  返回一个结果
    public String sayHello() {
        return "hello,world";
    }

    public void hello() {
        return;
    }

    public int max(int a, int b) {
        return a > b ? a : b;//三元运算符 a大于b 则返回a 否则返回b
    }
    
    //异常
    public void readFile(String file)throws IOException {
        
    }

}

方法调用

package com.oop;

public class Demo2 {

    //静态方法 static
    //非静态方法  必须实例化这个类new

    public static void main(String[] args) {
        //对象类型  对象名 = 对象值
        Student student = new Student();
        student.say();
    }

	//报错
    //和类一起加载
    public static void a(){
        b();
    }
    //类实例化之后才存在
    public  void b(){
    }
}



package com.oop;
//学生类
public class Student {
    //非静态方法
    public void say(){
        System.out.println("学生说话了");
    }

}

学生说话了

package com.oop;

public class Demo3 {
    public static void main(String[] args) {
        //实参和形参的类型要对应
        int add = Demo3.add(2, 3);
        System.out.println(add);
    }

    public static int add(int a,int b){
        return a+b;
    }
}

5

值传递

package com.oop;
//值传递
public class Demo4 {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);//1
        
        Demo4.change(a);
        System.out.println(a);//1
    }
    //返回值为空
    public static void change(int a) {
        a = 10;
    }
}

1

1

引用传递

package com.oop;

//引用传递:对象,本质还是值传递
public class Demo5 {
    public static void main(String[] args) {
        Person person = new Person();//实例化的过程
        System.out.println(person.name);//null
        Demo5.change(person);
        System.out.println(person.name);//Deer
    }

    public static void change(Person person) {
        //person是一个对象:指向的-->Person person = new Person();这是一个具体的人,可以改变属性
        person.name = "Deer";
    }

}

//定义了一个Person类,有一个属性:name
class Person {
    String name;//null
}

null
Deer

类与对象

关系

类:一种抽象的数据类型,对某移类十五整体描述、定义,但不能代表一个具体的事务

对象:抽象概念的具体实例

创建与初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建对象时,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
  • 类中的构造器也称为构造方法
  • 构造器的特点:1.必须和类的名字相同 2.必须没有返回类型,也不能写void

【注】:

定义了有参构造后,如果想使用无参构造,显示的定义一个无参构造

this.——当前类

package com.oop.Demo2;
//一个人项目应该只存在一个人main方法
public class Application {
    public static void main(String[] args) {
        //类:抽象的,实例化
        //类实例化后会返回一个人自己的对象
        //student对象就是一个Student类的具体实例
        Student student = new Student();
        Student xiaoming = new Student();
        Student xh = new Student();

        xiaoming.name="小明";
        xiaoming.age=3;

        xh.name="小红";
        xh.age=2;

        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);
        xh.study();

        System.out.println(xh.name);
        System.out.println(xh.age);
    }
}


package com.oop.Demo2;
//学生类
public class Student {

    //属性:字段
    String name;//null
    int age;//0



    //方法
    public void study(){
        System.out.println(this.name+"在学习");
    }
}

小明
3
小红在学习
小红
2

快捷键:ALT+Insert 构造函数

package com.oop.Demo2;
//一个人项目应该只存在一个人main方法
public class Application {
    public static void main(String[] args) {

        //new 实例化一个对象
        Person person = new Person("Deer");
        System.out.println(person.name);

    }

}


package com.oop.Demo2;
//java----->class
public class Person {
    //一个类即使什么都不写,它也会存在构造方法

    String name;
    //实例化初始值
    //1.使用new关键字,必须要有构造器
    //2.用来初始化值


    //无参构造
    public Person(){

    }
    //有参构造:一旦定义了有参构造,无参必须显示定义
    //重载
    public Person(String name){
        this.name=name;
    }

}

Deer

创建对象内存分析

堆——存放new的数组和对象

栈——存放基本变量类型和引用遍历

堆中方法区——存放常量池和class、static变量

小结

  • 类是模板、抽象,对象是具体实例

  • 方法——定义&调用

  • 对象引用:

    引用类型:基本类型

    对象通过引用来操作:栈—>堆(地址)

  • 属性:字段Field 成员变量

    默认初始化:

    ​ 数字:0

    ​ char:u0000

    ​ boolean:false

    ​ 引用:null

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

  • 对象的创建和使用

    必须使用new关键字创造对象,构造器 Person deer = new Person();

    对象的属性 deer.name

    对象的方法deer.sleep()

  • 类:

    静态的属性 属性

    动态的行为 方法

封装

  • 高内聚,低耦合
  • 高内聚:类的内部数据操作细尖自己完成,不允许外部干涉
  • 低耦合:仅暴露少量的方法给外部使用

封装——信息隐藏

属性私有——get/set

get——得到这个方法

set——给这个数据设置值

私有——private

意义:

  • 提高程序安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 增强系统可维护性

继承

  • 本质是对某一批类的抽象,从而实现现实世界更好的建模
  • 继承——extends
  • Java中只有单继承,没有多继承
  • 继承是类和类之间的一种关系
  • 继承关系的两个类一个为子类(派生类)一个为父类(基类)子类继承父类,使用关键字extends表示
  • 子类和父类具有 is a 的关系
  • 在Java中,所有的类都默认继承Object类

11.面向对象编程OOP_第1张图片

package com.oop.demo5;

//人:父类
public class Person {

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    private int money = 10_0000_0000;

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

}



package com.oop.demo5;
//学生 is 人    :派生类
//子类继承父类,拥有父类的全部方法
public class Student extends Person{
    //Ctrl+H

}



package com.oop.demo5;
//老师 is 人       :派生类
public class Teacher extends Person{
}




package com.oop;


import com.oop.demo5.Student;

//一个人项目应该只存在一个人main方法
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.say();

        System.out.println(student.getMoney());


    }
}

说话
1000000000

super

【注意点】:

  1. super调用父类的构造方法,必须在构造方法的第一个
  2. super不许只能出现在子类的方法灬构造方法中
  3. super和this不能同时调用构造方法

super&this:

  • 代表的对象不同:

    this:本身调用者这个对象

    super:代表父类对象的应用

  • 前提

    this:没有继承也可使用

    super:只能在继承条件才可以使用

  • 构造方法

    this():本类的构造

    super():父类的构造

package com.oop.demo5;

//人:父类
public class Person {
    public Person() {
        System.out.println("Person无参构造执行");
    }

    protected String name = "Deer";

    public void print(){
        System.out.println("Person");
    }


}



package com.oop.demo5;

//学生 is 人    :派生类
//子类继承父类,拥有父类的全部方法

public class Student extends Person {
    //Ctrl+H

    public Student() {
        //隐藏super,调用了父类的无参构造
        super();//调用父类构造器,必须要做子类构造器的第一行
        System.out.println("Student无参构造执行");
    }

    private String name = "Deer1";

    public void test(String name) {
        System.out.println(name);//Deer2传递来的
        System.out.println(this.name);//Deer1类中的
        System.out.println(super.name);//Deer父类的
    }

    public void print() {
        System.out.println("Student");
    }

    public void test1() {
        print();
        this.print();
        super.print();
    }
}



package com.oop;


import com.oop.demo5.Student;

//一个人项目应该只存在一个人main方法
public class Application {
    public static void main(String[] args) {


        Student student = new Student();

        student.test("Deer2");

        student.test1();
    }
}


Person无参构造执行
Student无参构造执行
Deer2
Deer1
Deer
Student
Student
Person

重写

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

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大,但是不能缩小
  4. 抛出的异常:范围可以缩小,但不能扩大

重写,子类的方法和不累必须一致,方法体不同

快捷键:Alt+Insert——>override

为什么需要重写:父类的功能,子类不一定需要,或者不一定满足

package com.oop.demo5;
//重写都是方法的重写,和属性无关

public class B {

    public void test(){
        System.out.println("B");
    }

}


package com.oop.demo5;
//继承
public class A extends B{

//    public void test(){
//        System.out.println("A");
//    }

    //Override——重写
    @Override//注解
    public void test() {
        System.out.println("A");
    }
}



package com.oop;


import com.oop.demo5.A;
import com.oop.demo5.B;
import com.oop.demo5.Student;

//一个人项目应该只存在一个人main方法
public class Application {


    //静态方法和非静态方法区别很大
    //静态和左边有关
    //非静态和右边有关————重写
    //静态方法是类的方法,非静态方法是对象的方法

    public static void main(String[] args) {

        //方法的调用只和左边,定义的数据类型有关
        A a = new A();
        a.test();//A

        //父类的引用指向了子类
        B b = new A();//子类重写了父类的方法
        b.test();//B

    }
}

A
A

多态

动态编译:类型——可扩展性

编译看左,运行看右

  • 多态是同一个方法可以根据发送对象的不同而采用不同的行为方式
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)

【注】:

  1. 多态是方法的多态,属性没有多态
  2. 父类和子类有联系 String——Person类型转换异常 ClassCastException
  3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象
  4. 不能重写——>不能多态:static属于类不属于实例、final常量、private私有,不能继承
package com.oop.demo6;

public class Person {
    public void run(){
        System.out.println("run");
    }
}

package com.oop.demo6;

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.demo6.Person;
import com.oop.demo6.Student;

//一个人项目应该只存在一个人main方法
public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //可以指向的引用类型就不确定了

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

        s1.run();
        s2.run();
        
        //对象能执行那些方法,主要看对象左边的类型,和右边关系不大
        ((Student) s2).eat();//子类重写了父类的方法,执行子类方法
        s1.eat();

    }
}

son
son
eat
eat

instanceof

引用类型

判断两个类是否存在继承关系

package com.oop;

import com.oop.demo6.Person;
import com.oop.demo6.Student;
import com.oop.demo6.Teacher;

//一个人项目应该只存在一个人main方法
public class Application {

    public static void main(String[] args) {
        //Object > Person > Student
        //Object > Person > Teacher
        //Object > String

        //System.out.println(X instanceof Y);能不能编译通过 看左边是否存在继承关系
        //ture和false看X指向的类型
        

        Object object = new Student();//object指向Student
        System.out.println(object instanceof Student);//ture
        System.out.println(object instanceof Person);//ture
        System.out.println(object instanceof Object);//ture
        System.out.println(object instanceof Teacher);//false
        System.out.println(object instanceof String);//false
        System.out.println("====================");
        
        Person person = new Student();//person指向Student
        System.out.println(person instanceof Student);//ture
        System.out.println(person instanceof Person);//ture
        System.out.println(person instanceof Object);//ture
        System.out.println(person instanceof Teacher);//false
        //System.out.println(person instanceof String);//编译报错
        System.out.println("====================");
        
        Student student = new Student();//student指向Student
        System.out.println(student instanceof Student);//ture
        System.out.println(student instanceof Person);//ture
        System.out.println(student instanceof Object);//ture
        //System.out.println(student instanceof Teacher);//编译报错
        //System.out.println(student instanceof String);//编译报错
    }
}

true
true
true
false
false
====================
true
true
true
false
====================
true
true
true
  1. 父类引用指向子类对象
  2. 把子类转换为父类,向上转型,直接转,丢失子类中原本可直接调用的特有方法
  3. 父类转换为子类,向下转型,强制转换,丢失父类被子类所重写掉的方法
  4. 方便方法调用,减少重复代码
package com.oop.demo6;

public class Student extends Person {

    public void go(){
        System.out.println("go");
    }
}



package com.oop.demo6;

public class Person {
    public void run(){
        System.out.println("run");
    }
}


package com.oop;

import com.oop.demo6.Person;
import com.oop.demo6.Student;
import com.oop.demo6.Teacher;

//一个人项目应该只存在一个人main方法
public class Application {

    public static void main(String[] args) {
        //类型之间转化:父   子
        //高       <-----      低
        //子类换位父类,可能丢失自己本来的一些方法
        Person obj = new Student();
        //student将这个当对象转换为Student类型,就可以使用student类型的方法了

        //高     ------->    低       强制转换
        Student student = (Student) obj;
        student.go();
        //或
        ((Student) obj).go();

    }
}

go
go

static

package com.oop.demo7;

public class Person {
    //第二个执行			赋初始值
    {
        //匿名代码块
        //创建对象时执行
        System.out.println("匿名代码块");
    }

    //第一个执行         只执行一次
    static {
        //静态代码块
        //类加载便执行
        System.out.println("静态代码块");
    }

    //第三个执行
    public Person() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("===========================");
        Person person2 = new Person();
    }
}

静态代码块
匿名代码块
构造方法
===========================
匿名代码块
构造方法
package com.oop.demo7;

public class Student {
    private static int age;//静态变量       多线程
    private double score;//非静态变量

    public void run() {
        go();
    }

    public static void 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);//实例变量

        new Student().run();
        go();
    }
}

0
0
0.0

package com.oop.demo7;

//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }
}

0.973071491187565
3.141592653589793

抽象类

abstract修饰

  1. 不能new这个抽象类,只能靠子类实现它
  2. 抽象方法必须在抽象类中
  3. 抽象类中可以写普通方法
  4. 抽象的抽象:约束

存在意义:

  • 提高开发效率
  • 可扩展性高
package com.oop.demo8;


//abstract:抽象类    类  extends   单继承       (接口可以多继承)
public abstract class Action {

    //约束   别人实现
    //abstract 抽象方法  只有方法名 ,没有方法实现
    public abstract void doSomething();

    public void hello(){
        System.out.println("hello");
    }
}


package com.oop.demo8;

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

接口

普通类:只有具体实现——class

抽象类:具体实现和规范(抽象方法)——abstract class

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

接口的本质是契约

接口的作用:

  1. 约束
  2. 定义方法,让不同的人实现 10————>1
  3. 默认方法public abstract
  4. 默认常量 public static final
  5. 接口不能被实例化,接口中没有构造方法
  6. implements 可以实现多个接口——多继承
  7. 必须重写接口中的方法

内部类

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类

成员内部类

package com.oop.demo10;

public class Outer {

    private int id = 10;

    private void out() {
        System.out.println("这是外部类的方法");
    }


    public class Inner {
        public void in() {
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性
        public void getID() {
            System.out.println(id);
        }
        //获得外部类的私有方法
        public void getOut() {
            out();
        }
    }
}



package com.oop;
import com.oop.demo10.Outer;
import com.oop.demo8.Action;

//一个人项目应该只存在一个人main方法
public class Application {

    public static void main(String[] args) {

        Outer outer = new Outer();

        //通过外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getID();
        inner.getOut();
    }
}

这是内部类的方法
10
这是外部类的方法

静态内部类

package com.oop.demo10;

public class Outer {

    private int id = 10;

    private void out() {
        System.out.println("这是外部类的方法");
    }

	//static
    public static class Inner {
        public void in() {
            System.out.println("这是内部类的方法");
        }
    }
}


package com.oop;
import com.oop.demo10.Outer;
import com.oop.demo8.Action;

//一个人项目应该只存在一个人main方法
public class Application {

    public static void main(String[] args) {

        Outer outer = new Outer();
    }
}

package com.oop.demo10;

public class Outer {

    //局部内部类
    public void method(){
        class Inner{
            public void in(){
                
            }
        }
    }

}
//一个Java类中可以有多个class类,但只能有一个public class
class A{
    public static void main(String[] args) {

    }
}

package com.oop.demo10;

public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();

        UserService userService = new UserService() {

            @Override
            public void hello() {
                
            }
        }
    }
}

class Apple {
    public void eat() {
        System.out.println("1");
    }
}

interface UserService {
    void hello();
}

你可能感兴趣的:(JavaSE学习笔记,javase,抽象类,多态,面向对象编程)