码迷,mamicode.com
首页 > 编程语言 > 详细

Java面向对象

时间:2021-07-05 17:07:48      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:default   get   value   ring   重写   对象内存   转型   pre   lan   

Java面向对象(Object-Oriented)

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

面向过程:步骤清晰简单,适合处理一些较为简单的问题

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

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

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

三大特性

  • 封装
  • 继承
  • 多态

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

从代码运行的角度考虑是先有类后有对象。类是对象的模板。

方法(加深)

方法的定义

  • 修饰符
  • 返回类型
  • break:跳出switch,结束循环和return
  • 方法名:规范
  • 参数列表:参数类型和参数名
  • 异常抛出

方法的调用

  • 静态方法

  • 非静态方法

    static是和类一起加载的。非静态方法需要实例化后才能存在。

  • 形参和实参

  • 值传递和引用传递

  • this关键字

对象

对象类型 对象名 = 对象值

Student student = new Student();

类和对象

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

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

张三是人的一个具体实例

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

使用new关键字创建对象

使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,并且构造方法

  • 必须和类的名字相同
  • 必须没有返回值,也不能写void

构造器是重点

构造器

快捷键alt+insert

  • 和类名相同,没有返回值

  • 一个类即使什么都不写,它也会存在一个方法,无参构造

  • 如果定义了有参构造,要显式的定义无参构造

  • 使用new关键字,本质上就是在调用构造器。初始化对象的值

对象内存分析

普通对象实例化

技术图片

  • 在堆中的方法区加在类Person的一些数据。
  • 在栈中开辟空间,申请一个地址存放p对象,这个p对象指向堆中的实例对象的地址,但是现在还没有。
  • 在堆中开辟空间,分配地址BE2500,对对象的属性进行默认初始化,然后进行程序员的显示初始化。
  • 构造函数进栈
  • 初始化完毕,将堆内存的地址赋给栈内的引用变量p。构造函数出栈。

子类对象实例化

技术图片

后续看JVM可回顾这里

封装

该露的露,该藏的藏

设计程序要追求“高内聚,低耦合”

高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉。

低耦合:仅暴露少量的方法给外部使用。

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

属性私有,get/set

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

  2. 隐藏代码的实现细节

  3. 统一接口

  4. 提高系统维护性

继承

属性:不可被重写,只可被隐藏

方法:会被重写,不会隐藏

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

继承是类和类之间的关系。除此之外还有依赖、组合、聚合等

子类默认调用了父类的无参构造

super是调用了父类的构造方法

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

super和this不能同时调用构造方法

vs this

代表对象

this代表调用者本身这个对象

super代表父类对象的应用

前提

this没有继承也可以使用

super只有在继承条件下才可以使用

构造方法

this()本类的构造

super()父类的构造

多态

前提

  • 存在继承或者实现关系
  • 重写
  • 父类引用指向子类对象

成员方法

  • 编译时:查看引用变量所属的类中是否有所调用的方法
  • 运行时:调用实际对象所属的类中的重写方法

成员变量

  • 不具备多态性,只看引用变量所属的类

所以多态跟new有关。

重载:本类中的同名方法,相同的名称实现不同的逻辑。

对象的多态---直接应用在抽象类和接口上

编译时类型和运行时类型

编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋值给该变量的对象决定

如果编译时类型和运行时类型不一致,就出现多态

  • 一个变量只能有一种确定的数据类型
  • 一个引用类型变量可能指向多种不同类型的对象
Person p = new Person();
Person e = new Student();//Person类型的变量e,指向Student类型的对象

向上转型:子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象

类变量类型

  • 一个引用类型变量如果声明为父类的类型,但实际引用的是子类的对象,那么该变量就不能再访问子类中添加的属性和方法

多态意思就是,以子类的模板生成了一个父类的实例。同名方法是子类的方法。同名属性是看左边,类型是谁就是谁的。子类独有的方法和属性不能访问(因为没有重写条件,无法触发多态)。

方法类型:虚拟方法调用

正常的方法调用。编译时和运行时一致

Person p = new Person();
p.getInfo();
Student s = new Student();
s.getInfo();

虚拟方法调用(多态)

Person e = new Student();
e.getInfo();//调用的是Student类的getInfo()方法

编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的方法。-----动态绑定

方法的重写和重载

重写:子类对父类方法的覆盖,属性是无法覆盖的,属性是隐藏。

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

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大但不能缩小 public>protected>default>private
  4. 抛出的异常:范围可以被缩小,但不能扩大ClassNotFoundException<Exception

重写:子类的方法和父类一致,但方法体不同。

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

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

//父类的引用指向了子类
B b = new A();
b.text();//B

静态方法是类的方法,非静态方法是对象的方法。

Person p = new Student
//Person类p  = new Student对象
//编译时        运行时

instanceof

A instanceof B

实例对象是否属于类B

对于正常继承关系

子类instance父类为true

对于多态

看右边实例对象

Object object = new Student;
//object实际上是Student的实例。
object instanceof Student;//true
//实际为Student instanceof Student
object instanceof Person;//true
//实际为Student instanceof Person
object instanceod Object;//true
//实际为Student instanceof Object

抽象类

用abstract修饰

  • 可以没有抽象方法,用abstract修饰就是抽象类了
  • 有抽象方法的一定就是抽象类
  • 抽象类无法被实例化
  • 抽象类的子类必须实现它的抽象方法

不用写方法的实现

主要用来捕捉子类的通用特性的,作为子类创建的模板

如果有一个接口,五个实现类,现在的需求可能要往接口加一个方法,这样要改变五个类,但是需求只需要改动其中两个实现类,可以再定义一个抽象类去实现这个接口,在抽象类中新增这个方法,然后其他两个实现类实现这个抽象就好了

==和equals方法

equals本质上等同于==

但是在引用比较上,equals重写了部分的方法,使之变为了值比较。

总结:==是用来引用比较的,equals是用来值比较的。目前有String、File、Date及包装类(WrapperClass)重写了equals的值比较,如果想将某类的引用比较改成值比较,需要重写该类的equals

String对象有两种创建方法

字面量创建String对象和new创建String对象

技术图片

包装类和toString

包装类:针对八种基本数据类型定义相应的引用类型

可以有类的特点,调用类的方法。

主要用来转换基本数据类型和字符串

基本数据类型对应的包装类

  • boolean ---> Boolean
  • byte ---> Byte
  • short ---> Short
  • int ---> Integer
  • long ---> Long
  • char ---> Character
  • float ---> Float
  • double ---> Double

装箱和拆箱

  • 装箱

    通过参数构造包装类对象

    Integer i = new Integer(500);
    Float f = new Float("4.56");
    Long l = new Long("200");
    
    //简便方法
    Integer i0 = 112;//自动装箱
    Boolean b0 = false;
    
  • 拆箱

    调用包装类的.xxxxValue()方法

    int i0 = i.intValue();
    boolean b0 = b.booleanValue();
    
    //简便方法
    int i0 = i;
    boolean b0 = b;
    

字符串和基本数据类型转换

  • 通过包装类的构造器实现

    int i = new Integer("12");//本质上还是调用了parseXxxx静态方法。因为Integer的String有参构造使用的就是parseXxxx方法。
    
  • 通过包装类的parseXxxx(String s)静态方法

    int i = Integer.parseInt("123"); 
    

基本数据类型转换成字符串

  • 调用字符串重载的valueOf()方法

    String str = String.valueOf(2.34f);
    
  • 更直接的方式

    String str = 5+"";
    

设计模式的单例设计模式

  • 单例类只有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 但李磊必须给其他所有对象提供这一实例

意图:保证一个类仅有一个实例,并且提供一个访问它的全局访问点

主要解决:一个全局使用的类频繁的被创建和销毁

何时使用:当你想控制实例数目,节省系统资源的时候

如何解决:判断系统是否已经有这个单例,有则返回,无则创建

关键代码:构造函数是私有的

实现:创建一个单例类,有它的私有构造函数和本身的一个静态实例,(因为静态只会创建一次)。提供静态方法,供外界获取它的静态实例。

饿汉式的单例模式

先静态创建一个实例,等别人通过方法调用。

懒汉式的单例模式

最开始不创建实例,等到第一个人调用时,创建对象,之后所有调用都返回这个对象

代码块

在new Person的时候

  1. 先加载类的默认初始化和显示初始化。即成员变量
  2. 执行非静态代码块的代码
  3. 执行构造函数

静态代码块:static修饰的代码块

  • 可以有输出语句
  • 可以对类的属性声明进行初始化操作
  • 不可以对非静态的属性初始化,不可以调用非静态的属性和方法
  • 若有多个静态的代码块,那么按照从上到下的顺序依次执行
  • 静态代码块的执行要先于非静态代码块
  • 静态代码块只执行一次

非静态代码块

  • 可以有输出语句
  • 可以对类的属性声明进行初始化操作
  • 可以调用静态和非静态的变量或方法
  • 若有多个非静态的代码块,那么按照从上到下的顺序依次执行
  • 每次创建对象的时候,都会执行一次,且先于构造器执行

final关键字

final修饰的类不能被继承。final是一个最终的类。

final修饰的方法不能被重写

final修饰的变量为常量,常量必须显式赋值

模板方法设计模式

当功能内部一部分实现是确定的,一部分实现是不确定的,这时可以把不确定的部分暴露出去,让子类去实现。

编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给子类实现,就是一种模板模式。

步骤

  1. 创建一个抽象类,它的模板方法被设置被final,里面会有一些未被实现的抽象方法。
  2. 创建子类继承抽象类,实现上述的抽象方法

接口implements

为了实现多继承

接口是抽象方法和常量值的定义的集合

接口是一种特殊的抽象类,这种抽象类只包含常量和方法定义,而没有变量和方法的实现

一个类可以实现多个接口,接口也可以继承其它接口

实现接口的类必须提供接口中所有方法的具体实现内容,才能被实例化,否则,仍为抽象类

先继承后实现

接口可以被接口继承,不能被实体类继承

接口的意义

当一个子类实例继承一个抽象父类时。

如果想要给父类增加抽象方法,则子类必须要实现它。

现在定义一个接口写抽象方法

让父类去实现抽象方法

让子类可选择实现或者不实现该接口

工厂模式

  1. 有一个抽象父类
  2. 子类继承父类
  3. 工厂类(给工厂提供子类属性和共有属性,产生子类实例。

内部类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

可以解决Java不能多继承的问题。

比如classA,想要继承classB和classC,直接是不可以的

但是我们可以在classA里面,写两个内部类,分别继承classB和classC,然后重写方法。内部类作为classA的成员,可以被调用。这样可以通过a.innerb.方法来实现原本的a.方法

调用外部属性

特性:

  • 内部类作为成员

可以声明为final

可以声明为private或protected

可以声明为static,但此时不能使用外层类的非static的成员变量

  • 内部类作为类

可以声明为abstract类,可以被其他内部类继承

注:非static的内部类的成员不能被声明为static,只有在外部类或者static的内部类中才可声明static成员

Java面向对象

标签:default   get   value   ring   重写   对象内存   转型   pre   lan   

原文地址:https://www.cnblogs.com/lxycc/p/14964895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!