面向对象(一)

前言:面向对象刚结束,不能拖赶紧来趁热打铁,进行面向对象整章节的梳理。

面向对象概念:

1.面向对象和面向过程区别:
面向过程到面向对象,是程序员思想上 从执行者指挥者的转变。
面向对象:当需要实现功能时,不关心具体步骤而是找一个已经具有该功能的人来做这个事情。
面向过程:实现功能每一个步骤必须要亲历亲为,详细处理每一个细节
2.面向对象由什么构成?
类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。
类由属性和方法组成:
· 属性:就相当于人的一个个的特征
· 方法:就相当于人的一个个的行为,例如:说话、吃饭、唱歌、睡觉

>>自己说:深刻理解面向对象的好处,不光是程序,程序实际上是人把好的思想用计算机实现了而已。

对象创建内存

1.栈存储的是:基本数据类型的数据 以及 引用数据类型的引用。

2.堆存放的是:类的对象所有类的对象都是通过new关键字创建 new关键字, 是指告诉JVM , 需要明确的去创建一个新的对象 ,去开辟一块新的堆内存空间。

3 . GC垃圾回收,当栈内存中不存在此对象的引用时,则视其为垃圾 ,等待回收

4.对象赋值,赋值的是地址

在这里插入图片描述

上面是Book b1 (默认值null)进栈 new Book进堆有一个地址,将地址赋值给了栈里的b1

在这里插入图片描述

上面这里是b2的代码执行过程

在这里插入图片描述

b2 = b1降b1的地址赋值给b2,那么0x124则没有栈内对象指向等待垃圾回收,下面再次执行b2.name =
"同苹果"则是在b1地址上赋值

匿名对象

匿名对象没有顾名思义没有创建对象,即在占内存中没有对象,直接在堆内存中创建,特点:只能使用一次,使用完GC回收

注意:一旦要使用对象次数大于等于2次必须创建对象,如果不创建则结果如下图:开辟了三个内存空间,最后调用的say()方法没有赋值,所以都是空值
在这里插入图片描述

this和static关键字

this

this

this表示的是当前对象,谁在调用类里的方法或属性,谁就是this
this的功能:
· 调用类中的属性
· 调用类中的方法或构造方法( 在一个构造方法中,调用另一个构造方法,调用代码必须写在构造方法第一行 )
· 表示当前对象

static

static

被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访 问。

重点

  1. 静态成员 在类加载时加载并初始化。普通方法,先创建对象,才能调用

  2. 无论一个类存在多少个对象 , 静态的属性, 永远在内存中只有一份( 可以理解为所有对象公用 )

  3. 静态修饰方法被调用时,可能对象还未被创建。

    在访问时: 静态不能访问非静态 , 非静态可以访问静态 !

代码块

普通代码块 在执行的流程中 出现的 代码块, 我们称其为普通代码块。
构造代码块 在类中的成员代码块, 我们称其为构造代码块, 在每次对象创建时执行一次, 执行在构造方法之前。

区别构造方法:无论用户调用哪一个构造方法来创建对象,构造代码块都必然执行,而构造方法只能调用一个,调用了有参就不会调用无参

静态代码块

在类中使用static修饰的成员代码块, 我们称其为静态代码块,
随着类的加载(第一次使用),静态代码块执行。类只加载一次,所以静态代码块也只执行一次。

准备唯一操作的资源放在静态代码块里。

在这里插入图片描述

**面试题:
构造方法 与 构造代码块 以及 静态代码块的执行顺序:
静态代码块先执行 --> 构造代码块 --> 构造方法**

继承extends详解

继承就是子类可以使用父类的特征和行为,使得子类对象具有父类的实例和方法,或子类从父类继承方法
在这里插入图片描述

子类实例化过程:
首先创建父类对象,父类对象创建完才会创建自己(student),并且父类对象会作为自己对象里的super,如果和父类有重名方法,优先使用子类自己的方法。如果没有则会通过super调用父类对象。
类似:Student.super.setName()

继承其实就是子类有了父类的地址而已

重写和重载的区别

重写:

重写应用于子调用父类方法,父类方法不适用于子类,可以在子类里重写一个新方法

在这里插入图片描述
在这里插入图片描述

方法重载(相同的方法名称):

1.方法名称相同

2.参数列表长度 或 参数列表类型 或 参数类型顺序不同

注意:与返回值类型无关

在这里插入图片描述


> 面试题:
> 重写重载区别:
> 1.重写发生在子类继承父类中;重载在一个类中,方法名相同,与返回值无关
> 2.参数列表在重写中必须相同,在重载中必须不同。重载除了方法名参数类型,
> 参数个数,参数参数顺序都可以不同
> 3.返回值类型 在重写中必须保持一致,重载中与返回值类型不相关
> 4.访问权限 重写 中子方法权限必须不能小于父方法权限,重载中与访问权限无关
> 5.异常处理 重写中异常范围可以更小,但是不能出新的异常;重载与异常无关
> 重写:发生子父类中,必须保持参数列表相同;
> 重载:发生在一个类中,方法名相同,参数类型,参数顺序,参数个数都可以修改。

抽象类

概念:
抽象类必须使用abstract class声明 一个抽象类中可以没有抽象方法。抽象方法必须写在抽象类或者接口中。

只声明而未实现的方法称为抽象方法(未实现指的是:没有“{}”方法体),抽象方法必须使用abstract关 键字声明。
原则:

1.抽象类本身是不能直接进行实例化操作的,即:不能直接使用关键字new完成。
2.一个抽象类必须被子类所继承,被继承的子类(如果不是抽象类)则必须覆写(重写)抽象类中的全部抽象方法。

抽象类和普通类的区别

1、抽象类必须用public或procted 修饰(如果为private修饰,那么子类则无法继承,也就无法实现其 抽象方法)。默认缺省为public
2、抽象类不可以使用new关键字创建对象, 但是在子类创建对象时, 抽象父类也会被JVM实例化。
3、如果一个子类继承抽象类,那么必须实现其所有的抽象方法。如果有未实现的抽象方法,那么子类也必须定义为 abstract类

**常见问题**

1、 抽象类能否使用final声明?
不能,因为final属修饰的类是不能有子类的,而抽象类必须有子类才有意义,所以不能。
2**抽象类能否有构造方法**?(面试题)
能有构造方法,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的
构造方法(默认是无参的),之后再调用子类自己的构造方法。

多态

概念:就是对象的多种表现形式,(多种体现形态)
多态的使用:对象的类型转换
类似于基本数据类型的转换:
· 向上转型:将子类实例变为父类实例
|- 格式:父类 父类对象 = 子类实例 ; ·
向下转型:将父类实例变为子类实例
|- 格式:子类 子类对象 = (子类)父类实例

instanceof关键字(instance实例)

如何判断 传入对象是此类型的哪种形态(哪个子类的对象)

作用:

判断某个对象是否是指定类的实例,则可以使用instanceof关键字 格式: 实例化对象 instanceof 类
//此操作返回boolean类型的数据

object类

Object类是所有类的父类(基类),如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。

tostring和equals

tostring:此方法的作用:返回对象的字符串表示形式。
Object的toString方法, 返回对象的内存地址

常见问题:
equals 和 == 的 区别
首先明确一点 equals比较内容, == 比较内容地址

看一段重写equals的代码
 @Override
    public boolean equals(Object o){
        //两个对象比较地址
        if (this == o){
            return true;
        }
        //不为空
        if(o == null){
            return false;
        }
        //判断o和personn类型一不一样
        if (o instanceof Person){
            Person p2 = (Person) o;
            if (this.name.equals(p2.name) && this.age == p2.age){
                //相同
                return true;
            }
        }else {
            return false;
        }
        //如果类型相同,name和age不相同 第二个if进不来 代码往下走直接到return false
        return false;
    }

明确记得equals和==的区别,看下面的代码

先别着急往下,自己先想一想四条sout输出的答案是什么?
public class Test {
    public static void main(String[] args) {
        String s1 = "123";
        String s2 = "123";
        String s3 = new String("123");
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
        System.out.println(s1 == s3);
        System.out.println(s1.equals(s3));
    }
}

在这里插入图片描述
不知道各位答案对否。下面讲讲为什么会这样

这里得新加一个Sring类的知识,具体会写一个博客讲String类。这里要记住,String s1一旦创建字符不会发生变化,内容会保存在一个叫永久代(随着版本叫法也不一样)的地方,s2创建它会直接去永久代里找到内容一样的s1,指向s1,即s1和s2共用同一个地址,所以无论是比较内容的equals还是比较地址的==都是true。
第四个sout应该没啥大问题,比较内容所以为true。
重点说一下第三个。乍看着和第一个没啥区别都是String创建字符串对象,但问题就出在这个new
上。虽然功能都一样,但是一旦使用了new,一定会在堆内存里开辟一个新空间,不然咋叫new呢?既然开了一个新空间也就是一个新地址, == 比较也就为false啦。

内部类

概念:可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

成员内部类: 成员内部类依赖于对象,对象创建了内部类才能去用

特点: 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,默认情况下访问的是成员内部类的成员。
如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
在这里插入图片描述

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或 者该作用域内。

注意:局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的

匿名内部类

在这里插入图片描述
在这里我们看到使用匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或者实现一
个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的。

注意:

在使用匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或 者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
6、只能访问final型的局部变量
ps: 1.8之前必须使用 final 1.8之后final可以省略。下面这个就是省略final后输出
在这里插入图片描述

 面试题:局部内部类或匿名内部类为什么只能访问final类型变量?
 内部类会单独编译成一个字节码文件,保证变量a和字节码文件中值相等,系统中限制了变量的值不可更改。
 a如果是个变量则备份里的值不会修改,会出现两边不对等,逻辑判断出错

静态内部类(静态只能访问静态成员)

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员 变量或者方法.

包装类

包装类内存示意图
在这里插入图片描述

装箱和拆箱

将一个基本数据类型变为包装类,那么这样的操作称为装箱操作。
将一个包装类变为一个基本数据类型,这样的操作称为拆箱操作,

自动装箱拆箱在这里插入图片描述

字符串转换

使用包装类还有一个很优秀的地方在于:
可以将一个字符串变为指定的基本数据类型,此点一般在接收输入数据上使用 较多。
在Integer类中提供了以下的操作方法:
public static int parseInt(String s) :将String变为int型数据
在Float类中提供了以下的操作方法:
public static float parseFloat(String s) :将String变为Float
在Boolean 类中提供了以下操作方法:
public static boolean parseBoolean(String s) :将String变为boolean

可变参数

语法: 返回值类型 方法名称(数据类型…参数名称)
{ //参数在方法内部 , 以数组的形式来接收 }
注意:可变参数只能出现在参数列表的最后。
在这里插入图片描述

异常:

概念:异常是在程序中导致程序中断运行的一种指令流。

异常指的是Exception。Exception类, 在Java中存在一个父类Throwable(可能的抛出)
Throwable存在两个子类:
1.Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。
2.Exception:一般表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。

Exception包含两个:受检异常和非受检异常
RuntimeException以外的异常都是受检查的,会飘红。
不受检查在运行阶段(runtimeException)可能会出错,不会飘红。
在这里插入图片描述

finally用法:只有在走finally之前内存都没了(停电,电脑自动关机)才不会执行,无论什么情况finally必定执行

在这里插入图片描述

这里即使程序return,终止会有一个程序准备阶段返回的阶段,这个准备阶段finally执行,然后再次执行return。下面程序很好的反应了finally必定执行

下面再来看一份代码

在这里插入图片描述
这段代码和上面一段代码区别:一个引用类型(person),还有一个是基本数据类型(int).

return 返回值,其实并不是真正返回上面对应值,而是返回其备份。
当返回是引用类型时,备份的是引用类型的地址,而finally里面修改的只是地址里的内容,所以返回会修改数据。

当返回是基本数据类型时,并不会开辟一个新堆内存,return备份的就是基本数据类型里的内容,然后执行finally,虽然finnally里面修改了数据,但是并不会修改return里备份的数据。所以返回值并不会因为finally而修改值。

##### 异常面试题

**GC只回收内存垃圾**,不回收蓝牙等硬件

1. try-catch-finally 中哪个部分可以省略?
   答: catch和finally可以省略其中一个 , catch和finally不能同时省略
     注意:格式上允许省略catch, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码.

2. try-catch-finally 中,如果 catchreturn 了,finally 还会执行吗?
   答:finally中的代码会执行

  详解:
  执行流程:

  ​	先计算返回值, 并将返回值存储起来, 等待返回

  ​	执行finally代码块

  ​	将之前存储的返回值, 返回出去;
  需注意:

  ​	返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不会改变

  ​	finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是trycatch中的值

  ​	如果在trycatch中停止了JVM,则finally不会执行.例如停电- -, 或通过如下代码退出
  JVM:System.exit(0);

抛出异常应该站在哪个角度思考?

在这里插入图片描述
通过传参导致异常,应该通过throws将异常抛出去。
运行时的异常(runtimeException)无论产生也好还是抛出去的都不会在代码上飘红线,不需要明确try catch或throws。
检查异常必须抛出去或try catch

在这里插入图片描述

throw关键字: RuntimeException 自己创造运行异常,通过出错误的方法告诉用户参数不合理,将错误扔出

RuntimeExcepion与Exception的区别

运行时异常,还有一个是检查时异常

注意观察如下方法的源码:
Integer类: public static int parseInt(String text)throws NumberFormatException

此方法抛出了异常, 但是使用时却不需要进行try。。。catch捕获处理,原因:
因为NumberFormatException并不是Exception的直接子类,而是RuntimeException的子类,只要是RuntimeException的子类,则表示程序在操作的时候可以不必使用try…catch进行处理,如果有异常发生,则由JVM进行处理。当然,也可以通过try catch处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值