【面向对象】java面向对象那些是是非非?

407 阅读19分钟

TOC

面向对象

OOP(Object Oriented Programming) POP(Procedure Oriented Programming) 面向对象(oop)与面向过程(pop) 二者是一种思想。面向对象相对于面向过程而言的,面向过程强调 功能行为,以函数为最小单位,考虑怎么做。面向对象,强调 具备了功能的对象,以类/对象为最小单位,考虑谁来做。 三大特征

  • 封装
  • 多态
  • 继承 程序员从执行者 转化成了指挥者 面向对象分析问题的思路与步骤:
  • 根据问题需要,选择现实中的实体
  • 从实体中寻找解决问题的属性和功能,形成现实中的类
  • 将抽象的实体用计算机语言描述
  • 将类实例化为计算机中的对象。

一、类与对象

  1. 类和对象(类是对象的抽象,对象是类的实体)
  • 类:是对一类具有相同属性和行为的事物的抽象(手机)
  • 对象:是真实存在的该类事物的物体(华为手机,老年机)
  1. 类 属性+行为 || 成员变量+成员方法

1. 属性方法

属性 + 行为

​ ||

成员变量Filed + 成员方法Method

2. 类与对象的使用

  1. 创建类,设计类成员
  2. 创建类的对象
  3. 通过 对象.属性 对象.方法

3. 对象的创建使用

类的访问机制:

  • 在同一个类中,类中的方法可以直接访问类的成员变量(例外:static方法访问非static,编译不通过)
  • 在不同类中,先创建访问类的对象,通过对象来访问类的成员变量

4. 内存解析

在这里插入图片描述

5. 匿名对象

不定义对象的句柄,而直接调用这个对象的方法。例如:new person().shout();

  • 一个对象只需要进行一次方法调用,就使用匿名对象
  • 经常用匿名对象来作为实参传递给一个方法使用

6. 属性(成员变量)与局部变量

区别成员变量局部变量
类中的位置不同类中方法外方法内或方法声明上
内存位置不同堆内存或静态域栈内存
生命周期不同随着对象而存在随着方法存在
初始化值不同有默认初始化值无默认,得先定义赋值后使用
修饰符private、public、static、final不能用权限修饰符final

二、(成员)方法Method

不可以在方法内定义方法 方法是类或对象行为特征的抽象,用来完成某个功能操作。

1. 重载overload

重载:在同一个类中,允许定义一种以上同名方法,只要它们的参数个数或者参数类型不同即可。 特点 与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或者参数类型) 调用时根据方法参数列表不同来区别

2. 传参

可变形参

  • 声明: 方法名(参数的类型名 ...参数名)
  • 方法参数指定是0个1个或者多个
  • 与同名的方法构成重载
  • 方法参数有可变形参的,放在参数最后面
  • 最多只能声明一个可变形参 参数传递机制
  • java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本传入方法内,而参数本身不受影响。
  • 基本类型:将实参的数据值传给形参
  • 引用类型:将实参的地址值传给形参

3. 递归

递归:一个方法调用自己本身 注意:要有递归出口 每次调用的返回值,局部变量都会分配栈空间,所以递归次数过多容易导致栈溢出 效率低,不推荐使用

4. 调用过程

在这里插入图片描述

三、封装与隐藏

追求高内聚,低耦合

  • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
  • 低耦合:仅对外暴露少量的方法用于使用 设计思想: 隐藏对象内部的复杂性,仅对外公开简单的接口。便于外部调用,从而提高系统的可扩展性、可维护性。"该隐藏的隐藏,该暴露的暴露" 封装原则 将类的某些信息隐藏在类的内部,不允许外部直接调用,而是通过成员变量private,提供对应的方法。

1. 信息的封装和隐藏

java通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和serXxx()实现对该属性的操作。 便于修改,增强代码的可维护性

2. 四种权限修饰符

对于类的权限修饰只能用public、default(缺省)

  • private 同一个类
  • default(缺省) 同一个包下
  • protected 不同包的子类
  • public 同一工程下 在这里插入图片描述

3. 构造器(构造方法)

不提供构造方法,自动默认无参构造方法;

一旦手动提供构造方法,则不再自动提供无参构造方法。 特征:

  • 与类同名
  • 不声明返回值类型(与声明void不同)
  • 不能被 static、abstract、final、synchronized、native修饰

作用 创建对象,给对象初始化

  • 默认构造器的修饰符与类的修饰符一致
  • 一个类可以创建多个重载的构造器
  • 子类不能继承父类的构造器

4. 属性赋值

四种赋值(顺序1->4): 1.默认赋值 2.显示初始化赋值 3.构造器中初始化 4.通过 对象.属性 对象.方法的方式赋值

5. JavaBean

javabean是一种java语言写成的可重用组件。 javabean指符合下面标准的类:

  • 类是公共的
  • 有一个无参的公共构造器
  • 有属性,且有对应的set、get方法

标准类

  • 成员变量: 使用private修饰
  • 构造方法: 提供无参、多参构造方法
  • 成员方法: 提供setXX、getXX方法、显示信息show

6. UML类图

在这里插入图片描述

7. This

解决局部变量隐藏成员变量 this作用 在方法内部使用,即这个方法所属对象的引用 在构造器内部使用,表示该构造器正在初始化的对象 this可以调用类的属性、方法、构造器 使用this 当在方法内需要用到调用该方法的对象时,就用this 比如:用this区分属性与局部变量

  • 可以在构造器中使用this(形参列表)的方式,调用本类中重载的其他构造器
  • 构造器不能通过this(形参)来调用自身
  • 一个类n个构造器,则最多有n-1个构造器使用了this(形参)
  • this(形参)必须生声明在类的构造器首行
  • 在构造器中,最多只能声明一个this(形参)

8. package

package

包就是文件夹,用来管理类文件的 

带包编译:javac–d.类名.java

​        例如:javac-d.  HelloWorld.java

带包运行:java包名+类名

​        例如:javacom.heima.demo.HelloWorld 

包名用小写字母,一般为公司域名的倒置 包的作用

  • 管理大型项目,将功能类似的划分同一个包
  • 包划分项目层次,便于管理
  • 解决类命名冲突的问题
  • 控制访问权限

9. MVC设计模式

MVC:常用设计模式之一,降低了耦合性 M:model 视图模型层---主要处理数据 V:view 视图层---view显示数据 C:controller 控制层---处理业务逻辑 在这里插入图片描述

10. import

import

使用不同包下的类时,使用的时候要写类的全路径,

写起来太麻烦了为了简化带包的操作,Java就提供了导包的功能 import告诉编译器要去哪里寻找类 import static 组合的使用:调用指定类或接口下的静态的属性或方法

四、继承

1. 继承性

父类:基类、超类

子类:派生类

对象在堆内存中,会单独存在一块super区域,用来存放父类的数据 继承好处与弊端

好处:复用性、可维护性

弊端:类的耦合性增强,父变化子不得不变 何时使用继承: A is B 的一种 继承中变量访问特点:

在子类方法中访问一个变量,采用的是就近原则。

  • 1.子类局部范围找

  • 2.子类成员范围找

  • 3.父类成员范围找

  • 4.如果都没有就报错(不考虑父亲的父亲... )

继承中构造方法访问特点:

注意:子类中所有的构造方法默认都会访问父类中无参的构造方法

子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()

问题:如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?

通过用super关键字显式的调用父类带参构造方法;或者在父类自己提供无参方法

继承中成员方法访问特点:

  • 1.子类成员

  • 2.父类成员

  • 3.找不到报错。

2. 方法重写

  • 子类出现了和父类中一模一样的方法声明, (方法名一样,参数列表也必须一样)

  • override注解:检查是否为重写方法

  • 方法重写的注意事项

    ​ 1.私有方法不能被重写(父类私有成员子类是不能继承的)

    ​ 2.子类方法访问权限不能更低(public>默认>私有) ​ 3.子类抛出的异常不能大于被重写方法抛出的异常 ​ 4.子类方法返回值类型不能更大

3. Super

super:代表父类存储空间的标识(父类对象的引用)

五、多态

1. 多态性

多态:对象不同时刻的不同状态,java中指父类的引用指向子类的对象 前提:

  • 有继承/实现关系
  • 有方法重写
  • 有父类引用指向子类对象

多态中成员变量访问

成员变量:编译看左边,执行看左边

成员方法:编译看左边,执行看右边(因为方法可以重写)

子类可以看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型 在这里插入图片描述

2. 向下转型

向下转型(强制类型转换)(造型):高级类->低级类 用instanceof来判断是否具有子类与父类关系(继承关系)

3. Object类

  • 所有类的根父类是Object类
  • 属于java.lang.Object
  • equals、hashCode(取得Hash码)、toString

4. ==与equals

在这里插入图片描述

面试题:==和equals的区别

1.== 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型 就是比较内存地址(是否同一对象) 2.equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也 是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中 用的比较多,久而久之,形成了equals是比较值的错误观点。 3.具体要看自定义类里有没有重写Object的equals方法来判断。 4.通常情况下,重写equals方法,会比较类中的相应属性是否都相等。

5. toString

Object里的方法,返回类名和它的引用地址 在这里插入图片描述

6. 包装类

八个基本类型提供了包装类! 一般首字母大写为包装类,除:int ---Integer; char ---Character 装箱:基本类型 --> 包装类 拆箱:包装类 --> 基本类型

包装类->基本:包装类.XxxValue()
字符串->基本类型:包装类.parseXxx()
基本->字符串:String.valueOf()

7. 基本、包装类、string之间转换

在这里插入图片描述

六、内部类、抽象类与接口(static、final、代码块、设计模式)

1. static

有些时候,我们希望无论是否产生对象或产生多少对象,某些特定的数据在内存中只有一份,供外部使用 哪些属性不因对象的改变而变,就设置为类属性,形影设置为类方法

  • static关键字是静态的意思,可以修饰【成员方法】,【成员变量】 ,【代码块】,【内部类】
  • 1.被类的所有对象共享,这也是我们判断是否使用静态关键字的条件
  • 2.可以通过类名调用,当然也可以通过对象名调用【推荐使用类名调用】

特点 随着类的加载而加载 优于对象 被所有对象共享 直接类来调用

被static修饰的变量叫做类变量 被static修饰的方法叫类方法 类方法

  • 类名.方法()来使用
  • 被static修饰的方法内部只能访问被static修饰的属性方法
  • 因为不需要实例就可以访问,所以static方法内部不能有this和super
  • static修饰的方法不能被重写

类变量的内存 在这里插入图片描述

2. 单例设计模式Singleton

设计模式 是在大量的实践中总结和理论化后优选的代码结构、编程风格以及解决问题的思考方式。类似于经典的棋谱==“套路” 饿汉式:

  对象预先加载,线程是安全的,在类创建好的同时对象生成,调用获得对象实例的方法反应速度快,代码简练。

public class Singleton {
    //私有化构造器
    private Singleton(){
    }
    //提供一个当前类的实例化
    //此实例必须静态化
    private static Singleton  singleton= new Singleton();

    //提供公共静态方法,返回当前类对象
    public static Singleton getInstance(){
        return singleton;
    }
}

懒汉式:   对象延迟加载,效率高,只有在使用的时候才实例化对象,但若设计不当线程会不安全,代码相对于饿汉式复杂,第一次加载类对象的时候反应不快。

public class Singleton {
    //私有化构造器
    private Singleton(){
    }
    //提供一个当前类的实例
    //此实例必须静态化
    private static Singleton  single;

    //提供公共静态方法,返回当前类对象
    public static Singleton getInstance(){
        if (single==null){
            single=new Singleton();
        }
        return single;
    }
}

优点 由于单例模式只生成一个实例,减少了系统性能开销, 当一个对象需要比较多的资源时,如:读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决! 应用场景 举例:java.lang.Runtime

public class Runtime{
    private static Runtime currentRuntime = new Runtime();
    public static Runtime getRuntime(){
        return currentRuntime;
    }
    private Runtime(){
 
    }
}

在这里插入图片描述

3. main

java虚拟机需要调用类的main方法,所以访问权限是public 不创建对象,所以是static 接收一个string数组参数,保存执行java命令时所运行的类的参数

4. 代码块

代码块作用 对类或对象进行初始化 一个类中的代码块如果被修饰,只能是static,称为静态代码块(static block);不被static修饰,称为非静态代码块

  • static 代码块通常为了初始化static的属性。 注意:代码块是从上往下执行 静态代码块:只能访问静态属性与方法,优于非静态代码块,随着类的加载而执行,且只执行一次 非静态代码块:访问所有,优于构造器,随着对象的创建而执行一次

5. final

  • Java中声明类、变量、方法时,可用final修饰,“最终的”
  • 1.final标记的类不能被继承。提高安全性,提高程序的可读性。 @String类、System类、StringBuffer类
  • 2.final标记的方法不能被子类重写。 @Object类中的getClass()
  • 3.final标记的变量称为常量。名称大写,且只能被赋值一次。 static final 为全局常量

6.抽象类与抽象方法

抽象类 是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类 用abstract修饰的类 抽象方法 用abstract修饰的方法;只有方法的声明,没有方法的实现。 public void add(int i);

  • 不能用abstract修饰变量、代码块、构造器
  • 不能用abstract修饰私有方法、静态方法、final方法、final类
  • 含有抽象方法的类必须声明为抽象类
  • 抽象类是不能被实例化,是用来被继承的,子类需要重写全部的抽象方法,并提供抽象体,否则子类仍为抽象类 含有抽象方法的类一定是抽象类,抽象类不一定含有抽象方法。

7.模板方法设计模式TemplateMethod

  • 多态的应用:TemplateMethod 解决的问题
  • 当功能内部一部分实现是确定的,一部分是不确定的。这时可以把不确定的部分暴露出去,让子类实现。
  • 也就是说,在软件开发中,整体步骤很固定、通用,这些步骤已经在父类中写好了。但在某些部分易变,易变部分可以抽象出来,供不同子类实现. 代码格式 类似于抽象类写法 应用 各个框架、类库中都有它的影子,比如:
    • 数据库访问的封装
    • Junit单元测试
    • JavaWeb的servlet中关于doGet、doPost方法调用
    • Hibernate中模板程序
    • Spring中的JDBCTemplate、HibernateTemplate等

8. 接口interface

接口 接口就是规范,定义的一组规则,体现了“如果你是/要...则必须能...”的思想。 继承是一个“是不是”的关系,而接口实现则是“能不能”的关系。 接口的本质是契约,标准,规范。 接口是抽象方法与常量的值定义的集合 1.接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。

Java中的接口更多的体现在对行为的抽象!

2.特点

  • 接口用interface修饰

  • 类实现接口用 implements表示

  • 接口不能实例化:可以参照多态形式,通过实现类实例化,叫做接口多态。

  • 多态的形式:具体类多态、抽象类多态、接口多态

  • 接口的子类

    要么重写接口的所有抽象方法,要么子类也是抽象类。

3.接口成员特点:

  • 成员变量: 只能是常量 public static final
  • 构造方法: 没有,接口主要是扩展功能,无具体存在
  • 成员方法: 只能是抽象方法 public abstract 《JDK1.7之前》

jdk1.8提出

  • 可以为接口添加静态方法和默认方法(用default修饰)
  • 当一个接口定义了默认方法,另一个接口也定义了同名同参方法(无论是否默认方法),实现类同时实现两个接口,出现“接口冲突”
  • 解决: 实现类必须覆盖接口中的同名同参方法
  • 如果接口定义了默认方法,而父类也定义了同名同参非抽象方法,不会出现冲突,因为遵守:类优先原则。接口方法被忽略。

9. 代理模式Proxy

代理对象   是java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。 在这里插入图片描述

10. 工厂模式

工厂模式Factory Pattern是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 意图:   定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 主要解决:   主要解决接口选择的问题。 何时使用:   我们明确地计划不同条件下创建不同实例时。 如何解决:   让其子类实现工厂接口,返回的也是一个抽象的产品。 关键代码:   创建过程在其子类执行。 优点:    1、一个调用者想创建一个对象,只要知道其名称就可以了。    2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。    3、屏蔽产品的具体实现,调用者只关心产品的接口。 使用场景:    1、日志记录器    2、数据库访问,    3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。

11. 接口与抽象类对比

NO.区别抽象类接口
1定义包含抽象方法的类包含抽象方法以及常量的集合
2组成构造方法、抽象方法、普通方法、常量、变量抽象方法、常量(jdk1.8:默认方法、静态方法)
3使用子类Extends子类implements
4关系抽象类可以实现多个接口接口不能继承抽象类
5常见使用模式模板方法简单工厂、工厂方法、代理模式
6对象都通过对象的多态性产生多态
7局限单继承无单继承局限
8实际模板标准、能力
9选择优先接口优先接口

12. 内部类

1.内部类: 在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类 。

2.内部类访问特点:

  • 可以直接访问外部类的成员,包括私有的
  • 外部类访问内部类,必须创建内部类的对象

3.成员内部类

  • 在类中方法,跟成员变量是一个位置
  • 格式:外部类名.内部类名对象名=外部类对象.内部类对象
  • 将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用
  • 编译生成OutClass$InnerClass.class字节码文件 4.局部内部类: - 局部内部类是在方法中定义的类 - 局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用 , 该类可以直接访问外部类的成员,也可以访问方法内的局部变量

5.匿名内部类

是一个继承了该类或者实现了该接口的子类匿名对象

6.匿名内部类开发中的使用

当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码

知识图谱

在这里插入图片描述 在线阅读:java面向对象

面向对象部分已更新完.......

在这里插入图片描述