JavaSE 第六章 面向对象

本文章基于b站:BV1RK4y1g7A5 赵珊珊老师的java课程的学习加以个人理解做出的学习笔记整理。(p117-p163) 

目录

引言

面向过程、对象的区别

类和对象的关系 

面向对象三个阶段

面向对象

创建

局部、成员变量区别

构造器

构造器的重载

内存分析(p127待完善)

 this关键字

static关键字

代码块 

包、import

三大特性

封装(Encapsulation)

继承(Inheritance)

内存分析

权限修饰符 (待补全)

 方法的重写

 super关键字

super修饰构造器 

面试题:继承条件下构造方法的执行过程

Object类

toString方法

equals方法

多态(PolyMorphism)

向上/向下转型 

简单工厂设计模式

抽象类面试题:

interface接口


引言

面向过程、对象的区别

面向过程:当事件比较简单的时候,利用面向过程,注重的是事件的具体的步骤/过程,注重的是过程中的具体的行为,以函数为最小单位,考虑怎么做
面向对象:注重找“参与者”,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做


面向过程--->面向对象,其实就是由执行者--->指挥者的一个过渡

面向过程:编年体,是以年代为线索编排有关历史事件的体裁

面向对象:纪传体,是指通过记叙人物活动反映历史事件的体裁

二者相辅相成并不是对立的。解决复杂问题,通过面向对象方式便于我们从宏观上把握事物之间复杂的关系、方便我们分析整个系统具体到微观操作,仍然使用面向过程方式来处理

类和对象的关系 

【1】万事万物皆对象
【2】
对象:具体的事物,具体的实体,具体的实例,模板下具体的产品
:对对象向上抽取出像的部分,公共的部分,形成类,类是抽象的,是一个模板
【3】一般在写代码的时候先写类,然后在根据类创建对象的对象。

面向对象三个阶段

【1】面向对象分析OOA -- Object Oriented Analysis

对象:张三,王五,朱六,你,我
抽取出一个类----》人类
类里面有什么:

名词--》静态特性--》属性
动词--》动态特性--》方法
【2】面向对象设计OOD -- Object Oriented Design先有类,再有对象:
类:人类: Person
对象: zhangsan , lisi, zhuliu
【3】面向对象编程OOP -- Object Oriented Programming

面向对象

创建

属性:

// Person属于引用数据类型

// 第一次加载类的时候,会进行类的加载,初始化创建对象的时候,对象的属性没有给赋值,有默认的初始化的值。

Person zs = new Person();
// 再次创建类的时候,就不会进行类的加载了,类的加载只在第一次需要的时候加载一次

方法:
//不同的对象,属性有自己的特有的值,但是方法都是调用类中通用的方法。

/属性:各个对象的属性是独立的
/方法:各个对象的方法是共享的

局部、成员变量区别

【1】:代码中位置不同
成员变量:类中方法外定义的变量(属性)
局部变量:方法中定义的变量代码块中定义的变量
【2】:代码的作用范围
成员变量:当前类的很多方法
局部变量:当前一个方法(当前代码块)
【3】:是否有默认值
成员变量:有

局部变量:没有

引用数据类型:null

【4】:是否要初始化
成员变量:不需要,不建议初始化,后续使用的时候再赋值即可

局部变量:一定需要,不然直接使用的时候报错
【5】:内存中位置不同
成员变量:堆内存

局部变量:栈内存
【6】:作用时间不同
成员变量:当前对象从创建到销毁
局部变量:当前方法从开始执行到执行完毕

构造器

Person p = new Person();

new关键字实际上是在调用一个方法,这个方法叫构造方法(构造器),没有任何参数的构造器我们叫做:空参构造器--》空构造器
调用构造器的时候,如果你的类中没有写构造器,那么系统会默认给你分配一个构造器,只是我们看不到罢了。可以自己显式的将构造器编写出来:
构造器的格式:
[修饰符] 构造器的名字(){
}
构造器和方法的区别:

1.没有方法的返回值类型
2.方法体内部不能有return语句
3.构造器的名字很特殊,必须跟类名一样
构造器的作用:

不是为了创建对象,因为在调用构造器之前,这个对象就已经创建好了,并且属性有默认的初始化的值。调用构造器的目的是给属性进行赋值操作的。
注意:我们一般不会在空构造器中进行初始化操作,因为那样的话每个对象的属性就一样了
实际上,我们只要保证空构造器的存在就可以了,里面的东西不用写

构造器的重载

public Person (String name, int age , double height) {
        //当形参名字和属性名字重名的时候,会出现就近原则

        //当类加载完成后,对象的创建和属性的初始化赋值操作已经完成了,可以用this关键字调用对象的属性
        //在要表示对象的属性前加上this.来修饰,因为this代表的就是你创建的那个对象

        this.name = name;
        this.age = age;
        this.height = height;

}

总结:

1.一般保证空构造器的存在,空构造器中一般不会进行属性的赋值操作

2.一般我们会重载构造器,在重载的构造器中进行属性赋值操作
3.在重载构造器以后,假如空构造器忘写了,系统也不会给你分配默认的空构造器了,那么你要调用的话就会出错了。

4.当形参名字和属性名字重名的时候,会出现就近原则:
在要表示对象的属性前加上this.来修饰,因为this代表的就是你创建的那个对象 

内存分析(p127待完善

public class Person {

        int id;

        int age;

        public static void main(String args[]){

                Person p1 = new Person();

                System.out.println(p1.age);// 0
        }

}

public class Person {

        int id;         int age;         String school;

        public Person(int a, int b, String c) {

                id = a;         age = b;         school = c;

        }

        public static void main(String[] args) {

                Person p = new Person(1, 20, "海淀");

        }

}

p127待完善

 this关键字

 this指代的就是当前对象
this关键字用法:
(1) this可以修饰属性:
总结:当属性名字和形参发生重名的时候,或者属性名字和局部变量重名的的时候,都会发生就近原则,

所以如果我要是直接使用变量名字的话就指的是离得近的那个形参或者局部变量,

这时候如果我想要表示属性的话,在前面要加上: this.修饰
如果不发生重名问题的话,实际上你要是访问属性也可以省略this.

(2) this修饰方法:
总结:在同一个类中,方法可以互相调用,this.可以省略不写。


(3) this可以修饰构造器:
总结:同一个类中的构造器可以相互用this调用,注意: this修饰构造器必须放在第一行

static关键字

【1】 static可以修饰:属性,方法,代码块,内部类。

【2】 staltic修饰属性

public class Test{

        int id; static int sid;

        psvm{

                Test t1 = new Test();        t1.id=10;        t1.sid=20;

        }

}

static修饰属性总结:
(1)在类加载的时候一起加载入方法区中的静态域中

(2)先于对象存在
(3)访问方式:对象名.属性名        类名.属性名(推荐)

static修饰属性的应用场景:某些特定的数据想要在内存中共享,只有一块--》这个情况下,就可以用static修饰的属性

属性:
静态属性(类变量)
非静态属性(实例变量)

 【2】 staltic修饰方法

(1)static和public都是修饰符,并列的没有先后顺序,先写谁后写谁都行

staltic修饰的先于对象存在

(2)在静态方法中不能访问非静态的属性

(3)在静态方法中不能访问非静态的方法
(4)在静态方法中不能使用this关键字;
(5)非静态的方法可以用对象名.方法名去调用
(6)静态的方法可以用 对象名.方法名 去调用,也可以用 类名.方法名 (推荐)
(7)在同一个类中可以直接调用

代码块 

【1】类的组成:属性,方法,构造器,代码块,内部类
【2】代码块分类:普通块,构造块,静态块,同步块(多线程)

【3】代码:

总结:
(1)代码块执行顺序:
最先执行静态块,只在类加载的时候执行一次,所以一般以后实战写项目:创建工厂,数据库的初始化信息都放入静态块。

—般用于执行一些全局性的初始化操作。
再执行构造块,(不常用)
再执行构造器,
再执行方法中的普通块。

public class test1 {
    int a;
    static int sa;

    public void a() {
        // 【3】
        System.out.println("----a");
        {
            System.out.println("普通代码块");
            int num = 10;
            System.out.println("普通代码块中的局部变量" + num);
        }
    }

    static public void b() {
        System.out.println("----b");

    }

    // 【2】
    {
        System.out.println("构造块");
    }

    //【1】
    static {
        System.out.println("静态块");
    }

    // 构造器
    public test1() {
    }

    public test1(int a) {
        this.a = a;
    }

    public static void main(String[] args) {
        test1 t = new test1();
        t.a();
        System.out.println();
        test1 t1 = new test1();
        t1.a();
    }

}

包、import

【1】生活案例:
邮寄快递:中国.北京.通州区.****小区.5号楼.3单元.101房.赵子龙

历史:常山赵子龙
【2】包的作用:
为了解决重名问题(实际上包对应的就是盘符上的目录)

解决权限问题
【3】包名定义:
(1)名字全部小写

(2)中间用.隔开
(3)一般都是公司域名倒着写: com.jd        com.msb

(4)加上模块名字:
com.jd.Iogin        com.jd.register
(5)不能使用系统中的关键字: nul,con,com1---com9.....

(6)包声明的位置一般都在非注释性代码的第一行

总结:
(1)使用不同包下的类要需要导包: import **.*.*;例如:import java.util.Date;

(2在导包以后,还想用其他包下同名的类,就必须要手动自己写所在的包。

(3)同一个包下的类想使用不需要导包,可以直接使用。
(4)在java.lang包下的类,可以直接使用无需导包:system.out.println(Math.random());

(5)可以直接导入*:import java.util.*;

【4】在java中的导包没有包含和被包含的关系:

设置目录平级的格式(不是包含和被包含的显示)∶

【5】静态导入:
import static java.lang.Math.* ;
//导入: java.Lang 下的Math类中的所有静态的内容

/在静态导入后,同一个类中有相同的方法的时候,会优先走自己定义的方法。

三大特性

封装(Encapsulation)

【1】 Java中封装的理解:
将某些东西进行隐藏,然后提供相应的方式进行获取。
封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装是一种信息隐藏技术,在java中通过关键字private,protected和public实现封装。
我们程序设计追求“高内聚,低耦合”。
高内聚:类的内部数据操作细节自己完成,不允许外部干涉;

低耦合:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
【2】封装的好处:
提高代码的安全性
【3】代码:通过一个属性感受封装:
上面的代码,对于属性age来说,我加了修饰符private,这样外界对它的访问就受到了限制,现在我还想加上其他的限制条件,但是在属性本身上没有办法再加了,所以我们通过定义方法来进行限制条件的添加。
以属性为案例:
进行封装:
(1) 将属性私有化,被private修饰--》加入权限修饰符一旦加入了权限修饰符,其他人就不可以随意的获取这个属性

(2) 提供public修饰的方法让别人来访问/使用
(3) 即使外界可以通过方法来访问属性了,但是也不能随意访问,因为咱们在方法中可以加入限制条件

继承(Inheritance)

【1】继承关系︰父类/基类/超类        子类/派生类
子类继承父类一定在合理的范围进行继承的        子类 extends 父类

【2】继承的好处:
1.提高了代码的复用性,父类定义的内容,子类可以直接拿过来用就可以了,不用代码上反复重复定义了

2.便于代码的扩展
3.为了以后多态的使用。是多态的前提
【3】父类private修饰的内容,子类也继承过来了。

【4】一个父类可以有多个子类。
【5】一个子类只能有一个直接父类。但是可以间接的继承自其它类。
【6】继承具有传递性:
Student --》继承自 Person ---》继承自 Object

Object类是所有类的根基父类
所有的类都直接或者间接的继承自Object。

内存分析

权限修饰符 (待补全)

 方法的重写

【1】重写:
发生在子类和父类中,当子类对父类提供的方法不满意的时候,要对父类的方法进行重写。
【2】重写有严格的格式要求:
子类的方法名字和父类必须一致,参数列表(个数,类型,顺序)也要和父类一致。
【3】重载和重写的区别:
重载:在同一个类中,当方法名相同,形参列表不同的时候多个方法构成了重载
重写:在不同的类中,子类对父类提供的方法不满意的时候,要对父类的方法进行重写。

 super关键字

【1】 super:指的是:父类的
【2】 super可以修饰属性,可以修饰方法;
在子类的方法中,可以通过 super.属性 super.方法 的方式,显示的去调用父类提供的属性、方法。

在通常情况下,super.可以省略不写
在特殊情况下,当子类和父类的属性重名时,你要想使用父类的属性,必须加上修饰符super.,只能通过super.属性来调用

在特殊情况下,当子类和父类的方法重名时,你要想使用父类的方法,必须加上修饰符super.,只能通过super.方法来调用

super修饰构造器 

【1】其实我们平时写的构造器的第一行都有: super() -->作用:调用父类的空构造器,只是我们一般都省略不写

(所有构造器的第一行默认情况下都有super(),但是一旦你的构造器中显示的使用super调用了父类构造器,那么这个super()就不会给你默认分配了。如果构造器中没有显示的调用父类构造器的话,那么第一行都有super(),可以省略不写)

【2】如果构造器中已经显示的调用super父类构造器,那么它的第一行就没有默认分配的super();了

【3】在构造器中,super调用父类构造器和this调用子类构造器只能存在一个,两者不能共存:因为super修饰构造器要放在第一行,this修饰构造器也要放在第一行:

面试题:继承条件下构造方法的执行过程

Object类

所有类都直接或间接的继承自Object类,Object类是所有Java类的根基类。

也就意味着所有的Java对象都拥有Object类的属性和方法。
如果在类的声明中未使用extends关键字指明其父类,则默认继承Object类。

toString方法

 总结: toString的作用就是对对象进行“自我介绍”,一般子类对父类提供的toString都不满意,都要进行重写。

equals方法

总结:
equals作用:这个方法提供了对对象的内容是否相等的一个比较方式,对象的内容指的就是属性。
父类Object提供的equals就是在比较==地址,没有实际的意义,我们一般不会直接使用父类提供的方法,而是在子类中对这个方法进行重写。

多态(PolyMorphism)

【1】多态跟属性无关,多态指的是方法的多态,而不是属性的多态。

【2】总结:
(1)先有父类,再有子类-->继承

先有子类,再抽取父类-->泛化

(2)什么是多态
多态就是多种状态:同一个行为,不同的子类表现出来不同的形态。

多态指的就是同一个方法调用,然后由于对象不同会产生不同的行为。
(3)多态的好处
为了提高代码的扩展性,符合面向对象的设计原则:开闭原则。

开闭原则:指的就是扩展是开放的,修改是关闭的。

注意:多态可以提高扩展性,但是扩展性没有达到最好,以后我们会学习反射
(4)多态的要素:
一,继承:Cat extends Animal ,Pig extends Animal,Dog extends Animal

二,重写:子类对父类的方法shout()重写
三,父类引用指向子类对象

public void play(Animal an){//Animal an = new Pig();

        an.shout();

}
 上面的代码,也是多态的一种非常常见的应用场合:

父类当方法的形参,然后传入的是具体的子类的对象,然后调用同一个方法,根据传入的子类的不同展现出来的效果也不同,构成了多态。

向上/向下转型 

Pig p = new Pig();

Animal an = p;//子类Pig向上转型为父类Animal

an.shout();

Pig pig = (Pig)an;//an是父类Animal类型,向下转型为Pig,才能访问到子类特有的属性方法

pig.eat();

pig.weight=60.8;

简单工厂设计模式

不仅可以使用父类做方法的形参,还可以使用父类做方法的返回值类型,真实返回的对象可以是该类的任意一个子类对象。
简单工厂模式的实现,它是解决大量对象创建问题的一个解决方案。将创建和使用分开,工厂负责创建,使用者直接调用即可。简单工厂模式的基本要求是
☆定义一个static方法,通过类名直接调用
☆返回值类型是父类类型,返回的可以是其任意子类类型
☆传入一个字符串类型的参数,工厂根据参数创建对应的子类产品

public class PetStore{//宠物店
        //方法:提供动物
        public static Animal getAnimal(String petName){//多态的应用场合(二)
        Animal an = null;
        if("猫".equals(petName)){//petName.equals("猫" )--》这样写容易发生空指针异常
            an =new Cat();
        }
        if("狗".equals(petName)){
            an =new Dog();
        }
        if("猪".equals(petName)){
            an = new Pig();
        }
        return an;
    }
}

测试类中:

Girl g = new Girl();

Animal an = PetStore.getAnimal("猪");

g.play(an);

抽象类面试题:

(1)抽象类不能创建对象,那么抽象类中是否有构造器?
抽象类中一定有构造器。构造器的作用给子类初始化对象的时候要先super调用父类的构造器。
(2)抽象类是否可以被final修饰?
不能被final修饰,因为抽象类设计的初衷就是给子类继承用的。要是被final修饰了这个抽象类了,就不存在继承了,就没有子类。

interface接口

1.类是类,接口是接口,它们是同一层次的概念。

2.接口中没有构造器
3.接口如何声明: interface
4.在JDK1.8之前,接口中只有两部分内容:
(1)常量:固定修饰符: public static final

(2)抽象方法:固定修饰符: public abstract
注意:修饰符可以省略不写,IDE会帮你自动补全,但是初学者建议写上,防止遗忘。

5.类和接口的关系是什么?实现关系        类实现接口
6.一旦实现一个接口,那么实现类要重写接口中的全部的抽象方法

在JDK1.8之后,新增非抽象方法:
(1)被public default修饰的非抽象方法:

注意1: default修饰符必须要加上,否则出错
注意2∶实现类中要是想重写接口中的非抽象方法,那么default修饰符必须不能加,否则出错。
(2)静态方法:
注意1: static不可以省略不写

注意2:静态方法不能重写
疑问:为什么要在接口中加入非抽象方法?
如果接口中只能定义抽象方法的话,那么我要是修改接口中的内容,那么对实现类的影响太大了,所有实现类都会受到影响。现在在接口中加入非抽象方法,对实现类没有影响,想调用就去调用即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值