面向对象总结

本文详细介绍了Java的面向对象编程概念,包括面向过程与面向对象的区别、类与对象的创建、构造器的使用、封装、继承和多态等核心特性。通过实例展示了如何进行值传递和引用传递,以及如何通过构造器初始化对象。此外,还探讨了类的封装作用,如隐藏数据和提供公共接口,以及继承和多态在代码复用和灵活性上的优势。最后,提到了抽象类和接口作为代码设计的约束和规范工具。
摘要由CSDN通过智能技术生成

一、初识面向对象

1.1 面向过程与面向对象

  1. 面向过程思想

    步骤清晰简单,第一步做什么,第二步做什么。。。。。。。

    面向过程适合处理一些较为简单的问题

  2. 面向对象思想

    物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。

    面向对象适合处理复杂的问题,适合处理需要多人协作的问题。

对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

1.2 什么是面向对象

Object-Oriented Programming OOP

1.2.1本质

​ 以类的方式组织代码,以对象来组织(封装)数据。

1.2.2三大特性

​ 封装

​ 继承

​ 多态

从认识的角度来看是先有对象后有类。对象是具体的事物,类是抽象的,是对对象的抽象。

从代码运行角度来看是先有类后有对象。类是对象的模版。

二、类与对象

2.1 值传递和引用传递

package com.oop.odemo01;

public class Demo02 {
    //区分值传递和引用传递
    //值传递
    public static void main(String[] args) {
        int a = 1;
        Demo02 demo02 = new Demo02();
        demo02.change(a);
        System.out.println(a);//输出的任然是1,因为Java是值传递
    }

    public void change(int a){
        a = 10;
    }
}
package com.oop.odemo01;

//引用传递:利用对象,本质还是值传递
public class Demo03 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);//null
        Demo03.change(person);
        System.out.println(person.name);//赵阳
    }

    public static void change(Person person){
        //person是一个对象,指向的是Person类
        person.name = "赵阳";
    }
}

//一个类里只能有一个public class,但可以有多个class
//再定义一个Person类,有一个属性
class Person{
    String name;//类变量,默认值为null
}

2.2 类与对象的创建

2.2.1 类与对象的关系

1、类是一种抽象的数据类型,他是对某一类事物的整体描述/定义,但是并不能代表某一个具体事物。

动物、植物、手机、电脑

Person类、Pet类、Cat类,这些类都是用来描述/定义某一类具体事物应该具备的特点和行为。

2、对象是抽象概念的具体实例。

张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。

能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

2.2.2 创建与初始化对象

一个项目应该是存在一个main方法,一下两个类都在同一个包里。

package com.oop.odemo02;

public class Student {
    //类里就是两个,属性和方法
    //属性:字段
    String name;
    int age;

    //方法
    public void study(){
        System.out.println(this.name+"学生在学习!");//this关键字是指当前类中的属性,super是继承的父类里的属性

    }

}


package com.oop.;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        //类是抽象的,需要实例化
        //类实例化后会返回一个自己的对象
        //student对象就是Student类的具体实例
        Student xiaoming = new Student();
        Student xiaohong = new Student();

        xiaoming.name = "小明";
        xiaoming.age = 20;
        System.out.println(xiaoming.name);//小明
        System.out.println(xiaoming.age);//20
        xiaoming.study();//小明学生在学习!

        xiaohong.name = "小红";
        xiaohong.age = 18;

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

2.2.3、构造器详讲

  • 使用new关键字创建对象的时候,除了分配内存空间之外,还会给创建好的对象进行默认初始化以及对类中构造器的调用
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

​ 1、必须和类的名字相同;

​ 2、必须没有返回类型,也不能写void。

package com.oop.odemo02;

public class Person {
    //一个类即使什么都不写,它也会存在一个方法
    //显试的定义一个构造器

    String name;
    //作用:实例化初始值
    //1、使用new关键字必须有构造器
    public Person(){
        this.name = "zhaoyang";
    }
    //有参构造,一旦定义了有参构造,无参构造就必须显试定义,也就是有了当前的有参构造,上边的无参构造就必须写出来
    public Person(String name){
        this.name = name;//指的是实参传进来的name
    }
}

package com.oop;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        Person person = new Person();//Person类为空,但仍可以new一个对象,说明类里存在默认的方法,就是构造方法
        System.out.println(person.name);
        Person person1 = new Person("xiaoming");//此处是方法重载
        System.out.println(person1.name);//xiaoming
    }
}//Windows使用control+insert,Mac使用command+n自动添加构造器,默认是有参构造器,点击select none是无参构造器


/*
构造器:
    1、和类名相同
    2、没有返回值
作用:
    1、new本质在调用构造器,也就是构造方法
    2、初始化对象的值
注意点:
    1、定义有参构造器之后,如果想使用无参构造,就必须显试定义无参构造,无参构造本来是默认存在的,但是是隐藏着的。
 */

三、Java三大特性——封装、继承、多态

3.1 封装

3.1.1 概述

1、该露的露,该藏的藏。

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

2、封装(数据的隐藏)

​ 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

封装的属性私有,使用get/set方法来操作私有的属性。

package com.oop.odemo03;

//类,封装的属性是私有的,private
public class Student {

    private String name;//名字
    private int id;// 学号
    private char sex;// 性别
    private int age;//年龄,且必须合理
    //属性私有,但是有一些可以操作私有属性的方法
    //提供的一些public的get、set方法
    //get获得这个属性的值
    public String getName(){
        return this.name;
    }
    //set给这个属性赋值
    public void setName(String name){
        this.name = name;
    }

    //为age添加get、set方法


    public int getAge() {
        return age;
    }
//将一些判断写在了set方法里
    public void setAge(int age) {
        if (age>120||age<0) {
            this.age = 3;
        }else{
            this.age = age;
        }
    }
}//使用构造方法的快捷键能自动生成get、set方法


package com.oop;

import com.oop.odemo03.Student;

import java.util.Scanner;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();//该类中属性私有,不能直接s1.name
        s1.setName("zhaoyang");
        System.out.println(s1.getName());

        s1.setAge(999);
        System.out.println(s1.getAge());//3,这样就把一些判断就写在set方法里
    }
}

3.1.2 封装的意义

​ 1、提高程序的安全性,保护数据;

​ 2、隐藏代码的实现细节;

​ 3、统一接口;

​ 4、增加系统可维护性。

3.2 继承

3.2.1 概述

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

extends的意思是扩展。子类是父类的扩展。

  • Java中只是单继承,没有多继承。
  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
  • 子类和父类之间,从意义上讲应该具有“is a”的关系。例如Student类继承Person类,Teacher类继承Person类,Student is Person,Teacher is Person。
package com.oop.odemo04;

//人 父类
public class Person {
    //public        按优先级排列
    //protected
    //default     默认的
    //private
    private int money = 1000000000;
    public void say(){
        System.out.println("说了一句话");
    }

    public int getMoney() {
        return money;
    }

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

==================================================================
package com.oop.odemo04;

//学生 is 人,子类/派生类
//子类继承了父类就会拥有父类的全部方法!
public class Student extends Person {
}

====================================================================
package com.oop.odemo04;

//Teacher is 人,子类/派生类
public class Teacher extends Person {
}

====================================================================
package com.oop;
import com.oop.odemo04.Student;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.say();
        System.out.println(student.getMoney());
    }
}

3.2.2 Object类

在Java中所有的类都默认直接或间接继承object类。

​ 当前Person类里没有写任何方法,但在主类里仍可以调用Person类里的方法,且control+h显示继承树,继承了Object类。

在这里插入图片描述

3.2.3 super

先是通过this和super关键字调用属性的例子。

再是通过this和super关键字调用方法的例子。

最后是调用构造器的例子。

package com.oop.odemo04;

//在Java中所有的类都默认直接或间接继承object类
//人 父类
public class Person {

    public Person() {
        System.out.println("Person执行了");
    }

    protected String name = "feiying";
    //私有的东西无法被继承
    public void print(){
        System.out.println("Person");
    }
}

=================================================================================
package com.oop.odemo04;

//学生 is 人,子类/派生类
//子类继承了父类就会拥有父类的全部方法!
public class Student extends Person {
    public Student() {//构造器
        //Person这句话在Student这句话先输出
        //所以有隐藏代码,调用了父类的无参构造方法,所以Person先输出
        super();//这就是隐藏的代码,默认调用,可以不写。
        // 调用父类的构造器必须写在子类的第一行,写在第一行的事super()方法,写在之后的是super关键字
        System.out.println("Student执行了");
    }

    private String name = "zhaoyang";

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

    public void test1(){
        print();//当前类的方法,但是表述不清晰,因为Person类里也有print()
        this.print();//当前类的方法
        super.print();//继承Person类的print()
    }

    public void test(String name){
        System.out.println(name);//当前形参接收到的name
        System.out.println(this.name);//是Student类中的变量name
        System.out.println(super.name);//Student类继承的Person类中的name
    }
}

=================================================================================
package com.oop;

import com.oop.odemo04.Student;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("slxy");
        student.test1();

    }
}
结果:
Person执行了
Student执行了
slxy
zhaoyang
feiying
Student
Student
Person

  • super注意点

​ 1.super();是调用父类的构造方法,必须写在构造方法的第一行。

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

​ 3.super和this不能同时调用构造方法!

  • this VS super

​ 1.代表的对象不同:

​ this:本身调用的这个对象

​ super:代表父类对象的应用

​ 2.使用条件不同:

​ this:没有继承关系也可以使用

​ super:只能在继承的条件下使用

​ 3.构造方法中的使用:

​ this();调用本类中的构造方法

​ super();父类的构造方法

3.3.4 方法重写

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

注:1、方法名必须相同且只能是静态方法

​ 2、参数列表必须相同

​ 3、修饰符:范围可以扩大public>protected>default>private

​ 4、抛出的异常:范围可以缩小,但不能扩大。

重写,子类的方法和父类的必须一致,只是方法体不同!

二、为什么需要重写

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

​ 2、Alt+insert,command+n,选择override method自动生成重写的代码

重写的会有这个标记

在这里插入图片描述

package com.oop.odemo04;

//重写都是方法的重写,与属性无关
public class A extends B{//A继承B并且重写B中的方法
    //override 重写
    public void test(){
        System.out.println("A==>test");
    }
}

=========================================================
package com.oop.odemo04;

//重写都是方法的重写给,与属性无关
public class B {
    public void test(){
        System.out.println("B==>test");
    }
}

=========================================================
package com.oop;

import com.oop.odemo04.A;
import com.oop.odemo04.B;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    //静态的方法和非静态的方法区别很大
    //静态方法:方法的调用只和左边的数据类型有关
    //非静态方法:重写只和非静态方法有关
    public static void main(String[] args) {
        A a = new A();//A类的方法
        a.test();//A==>test

        //A类和B类有继承关系,子类可指向父类从右至左
        //父类的引用指向了子类从右至左
        //方法的调用只和左边的数据类型有关
        B b = new A();//子类重写了父类的方法,B类的方法
        b.test();//A==>test
    }
}

3.3 多态

3.3.1 概述

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

​ 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。

3.3.2 多态存在的条件:

​ 1、有继承关系

​ 2、子类重写父类方法

​ 3、父类引用指向子类对象

注:多态是方法的多态,属性没有多态。

package com.oop.odemo05;

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

=========================================================
package com.oop.odemo05;

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.odemo05.Person;
import com.oop.odemo05.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();

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

        s2.run();//son,子类重写了父类方法,那么就执行子类的方法
        s1.run();//son
        s1.eat();//eat
        ((Student) s2).eat();//父类不能调用子类的方法,所以强制类型转换
    }
}

四、instanceof和类型转换

instanceof判断有没有父子关系

instanceof实际上判断一个变量所指向的实例是否是指定的类型,或者是这个类型的子类。

package com.oop;

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

//用作启动类,一个项目应该是存在一个main方法
//其中,Student和Teacher继承Person
public class Application {
    public static void main(String[] args) {
        //Object >Person >Student
        //Object >Person >Teacher
        //Object >String
        Object o = new Student();
        //instanceof实际上判断一个变量所指向的实例是否是指定的类型,或者是这个类型的子类。
        System.out.println(o instanceof Student);//true,o实例是指向Student类的
        System.out.println(o instanceof Person);//true,Student继承Person
        System.out.println(o instanceof Object);//true,所有类默认继承Object
        System.out.println(o instanceof Teacher);//false,Student和Teacher并无关系
        System.out.println(o instanceof String);//false,Student和String无关系
        System.out.println("===================================");

        Person person = new Student();
        System.out.println(person instanceof Student);//true,person实例是指向Student类的
        System.out.println(person instanceof Person);//true,
        System.out.println(person instanceof Object);//true,所有类默认继承Object
        System.out.println(person instanceof Teacher);//false,Student和Teacher并无关系
        //System.out.println(person instanceof String);//编译报错

        System.out.println("===================================");
        Student student = new Student();
        System.out.println(student instanceof Student);//true
        System.out.println(student instanceof Person);//true,Student继承Person
        System.out.println(student instanceof Object);//true,所有类默认继承Object
        //System.out.println(student instanceof Teacher);//编译报错
        //System.out.println(student instanceof String);//编译报错
    }
}

注:

​ 1、父类引用指向子类对象。

​ 2、把子类转换为父类,向上转型,自动转换。

​ 3、把父类转换为子类,向下转型,强制转换。

​ 4、方便方法的调用,减少重复的代码,简洁。

package com.oop;

import com.oop.odemo05.Person;
import com.oop.odemo05.Student;

//用作启动类,一个项目应该是存在一个main方法
public class Application {
    public static void main(String[] args) {
        //类型之间的转换:父子之间
        //低转高自动转换
        //高          <==        低
        Person person = new Student();
        //但person不能执行Student里但go方法,所以需要强制类型转换
        ((Student) person).go();//同下面
        //将person实例强制转换为Student,高转低,只需键入(Student)person按转option+回车
        Student person1 = (Student) person;
        person1.go();

    }
}

五、static详解

package com.oop.odemo06;

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

    public void run(){

    }//不能直接调用

    public static void go(){

    }//可直接调用,static是和类一块加载,也就是比非static方法要早存在

    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println(age);//或者Student.age
        //System.out.println(Student.score);//score不是静态变量所以不能直接调用,报错
        System.out.println(s1.age);
        System.out.println(s1.score);
        s1.run();
        go();
    }
}

=====================================================================================
  
  package com.oop.odemo06;

public class Person {
    /*
    static{
            }静态代码块,只执行一次,不加static的叫做匿名代码块
     */
    {
        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.odemo06;
//静态导入包
import static java.lang.Math.random;
public class Test {
    public static void main(String[] args) {
        //System.out.println(Math.random());静态导入包之后就可以直接写random了
        System.out.println(random());
    }
}

六 抽象类

特点:
1、不能new这个抽象类,只能靠子类去实现它:约束!
2、抽象类可以写普通方法。
3、抽象方法必须在抽象类中。

继承了抽象类的方法,都必须实现他的方法,也就是重写方法。

package com.oop.odemo07;

//abstract 抽象类
public abstract class Action {
    //只有方法的约束,没有方法体,方法体给别人来实现
    //抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();
    /*
    特点:
        1、不能new这个抽象类,只能靠子类去实现它:约束!
        2、抽象类可以写普通方法。
        3、抽象方法必须在抽象类中。
     */
}


package com.oop.odemo07;

//继承了抽象类的方法,都必须实现他的方法,也就是重写方法,implement,除非子类也是抽象类那就没必要实现父类的抽象方法
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

七、接口

7.1 对比

  • 普通类:只有具体实现,也就是有方法和方法体。
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!规范就是抽象方法。无法自己写方法,专业的约束,实现约束和实现分离。
  • 声明接口的关键字是interface。
  • 接口中的所有定义都是抽象的public,可以不用写public abstract。
  • 实现了接口中的类,就必须重写接口中的方法,因为是抽象类。
package com.oop.odemo08;

//interface接口定义的关键字,接口都需要有实现类
public interface UserService {
    //接口里定义的属性是常量,public static final是默认的
    int age = 99;
    //接口中的所有定义都是抽象的public,可以不写public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
/*
接口的作用:
        1、约束
        2、定义一些方法,让不同的人实现
        3、public abstract
        4、public static final
        5、接口不能被实例化,接口中没有构造方法
        6、implement可以实现多个接口
        7、必须重写接口中的方法
 */


=====================================================================================
package com.oop.odemo08;

//类可以实现接口,使用implement关键字,
//extends是单继承,而接口可以多继承
//实现了接口中的类,就必须重写接口中的方法
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) {

    }

    @Override
    public void timer() {

    }
}


=====================================================================================
package com.oop.odemo08;

public interface TimeService {
    void timer();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值