JavaSE入门笔记(七)
Java面向对象(课程笔记)
课程来源 狂神说Java
由于笔者本人有着c语言的学习基础,故Java等等学习笔记有很多省略之处,多用以自己复习巩固
01 初识面向对象
面向过程和面向对象
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理
什么是面向对象
- 面向对象编程(Object-Oriented Programming,OOP)
- (记住)面向对象编程的本质就是:以类的方式组织代码,以对象的方式组织(封装)数据
- 抽象
- 三大特性:
-
- 封装
-
- 继承
-
- 多态
- 从认识论角度考虑,是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑,是先有类后有对象。类是对象的模板。
02 方法回顾和加深
- 静态方法伴随类加载就加载,而非静态方法需要实例化为对象才加载
静态方法(static):可以直接通过类名调用,类名.方法名
非静态方法:无法直接通过类名调用,对象名.方法名
如果不是都是静态方法或者非静态方法,不可相互调用,下图是错误情况:
基础类型存值,引用类型存地址
值传递:形参类型为基本数据类型,形参的值改变,实参未改变
引用传递:形参类型为类,形参为对象,引用对象,形参改变,实参也改变
03 对象的创建分析
类与对象的关系
创建与初始化对象
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是在进行
一个项目中应该只存在一个main方法,在该项目中,对其他类的定义不要有main方法
实例
运行结果
构造器详解
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
-
- 1、必须和类的名字相同
-
- 2、必须没有返回类型,也不能写void
- 构造器必须要掌握
IDEA打开class文件:将class文件导入目录
Project Structure -> Modules -> +Add Content Root -> 导入包含class文件的文件夹
- 1、一个类即使什么都写,它也会存在一个方法(构造器):一个类即使什么都不写代码,在main方法中定义一个实例化对象,编译后,打开class文件可知,会默认初始化一个与方法同名的空方法,其实这就是一个构造器;故在类中与类同名的且没有任何类型的方法,是为构造器。
- 2、使用new关键字,本质上是在调用构造器
- 3、**有参构造:一旦定义了有参构造,无参就必须显示定于。**如果使用了有参构造,则要保留空的无参构造器,对象的创建需要再无参造器的存在
- 4、构造器是用来初始化值的
- Alt+Insert快捷生成无参/有参构造器
调用的一个对象时,会自动且先运行无参构造器
创建对象内存分析
实例代码内存分析
1.类的代码信息先于方法区加载,字符串是常量(final),int型数据age不是,age不在常量池
2、执行main方法,故main方法首先加载进入栈,在栈最底下(最先进入,最后弹出),当main方法弹出时,栈结束了,程序也执行完毕
3、执行main方法中代码创建一个Pet类dog对象
我们通过Debug调试查看
然后加载Pet类的代码信息至方法区
通过Pet类的信息,生成一个具体的dog对象,在栈中加载dog(只是引用对象名,本质在堆中生成和分配内存空间,实质是先在堆中加载,然后再在栈中加载)
继续执行main方法
补充:静态方法区
所有的对象都可以直接调用它
方法区属于堆(JDK7之前方法区在堆中,JDK8之后移至本地内存),栈里面都是方法和引用变量
04 面向对象三大特性
封装
封装大部分针对属性,少部分包括方法
Alt+Insert 可以自动生成get/set方法
这些get/set方法是可以自行定义的,参数列表的实现代码都可以自定义
特点:
- 提高程序的安全性,保护数据;
- 隐藏代码的实现细节;
- 统一接口;
- 系统可维护增加了。
继承
子类继承父类的所有public或者默认的default(通常省略default修饰词)属性(包括方法),private属性不能继承
四种修饰符:public protected default private
Ctrl+H,打开继承树,查看继承关系
在Java中,所有的类都默认继承object类
private修饰的,私有的东西无法被继承
super详解
类似于this,不过指的是上一级,this是用来调用当前这一级的属性,super是用来调用上一级的,即父类的属性
- 如果定义了有参构造且不定义无参构造,那么无参构造就不会默认生成。如果父类的无参构造不存在,则在子类无参构造中的隐藏代码super()也运行不了,继而子类的无参构造也运行不了
- 故一般来说,一个类如果写了有参构造,则必须要写上无参构造
或者也可以直接调用父类的有参构造,super(属性)
super注意点:
- super 调用父类的构造方法,必须在构造方法的第一个;
- super 必须只能出现在子类的方法或构造方法中;
- super 和 this 不能同时调用构造方法;
super 与 this 的不同点:
- 代表对象不同:
- this : 本身调用者这个对象
- super :代表父类对象的应用
- 前提不同:
- this : 没有继承也能使用
- 只能在继承条件下才可以使用
- 构造方法不同
- this() :本类的构造
- super() : 父类的构造
方法重写
- 为什么要方法重写:
父类的功能,子类不一定需要,或者不一定满足;
方法重写 只跟非静态方法有关
静态方法在类一加载就已经加载了,而非静态方法需要对象加载
重写都是方法的重写,和属性无关
静态方法实例
用Alt+Insert选择的Overdide…可以快捷生成重写方法
因为静态方法是类的方法,而非静态方法是对象的方法,即b是A new出来的对象,因此调用了A类对象的方法,不是A的类方法
static修饰符可以直接不需要创建类,是类的方法。直接 类名点 的方式可以在main方法中调用。
非静态方法实例
- 默认调用
下面代码中进行了方法重写,故调用的都是(子类)A类对象的text()方法,而这个方法中调用了父类的test()方法,即B的test()方法。
- 不默认调用,自己定义
调用也是不调用父类方法
小结
- 优先级是 类高于对象
- 静态方法:方法的调用只与左边、定义的数据类型有关,左边定义的是 类,不能重写
- 非静态方法:可以重写的只能是public非静态方法
- private私有方法不能重写
- 重写需要有继承关系,方法重写只能存在父子类之间,而且只能是子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 方法体可不同
- 修饰符:范围可以扩大,不可以缩小
public -> protected ->default ->private - 抛出的异常:重写可能会抛出异常,范围可以被缩小,但不能扩大,即重写异常范围不能大于父类。
ClassNotFoundException(小) -> Exception(大)
多态
- 一个对象的实际类型是确定的;
- 可以指向的引用类型就不确定了:父类的引用指向子类,但是不可以是子类引用父类;
-
子类重写了父类的方法,执行子类的方法;
- 对象能执行哪些方法,主要看对象定义的类型,看左边,和右边关系不大;
-
子类能调用的方法都是自己的或者继承父类的,如下例中的Student类,而父类可以指向子类,但不能调用子类独有的方法
多态注意事项:
- 多态是方法的多态,与属性无关;
- 父类和子类,有联系 类型转换异常,ClassCastException;
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象-> Father f1 = new Student;
- 不能重写的方法:
1. static 方法,属于类,不输于实例;
2.final 方法,常量;
3. private 方法。
instanceof : (类型转换)引用类型,判断一个对象是什么类型~
X instanceof Y --> 在编译通过的前提下,判断对象X是不是属于Y类,主要用右边的对象实际类型与判断的类型比较,是则返回true,否则返回false。
代码的运行分为编译和运行两步,是否会编译错误,主要看左边定义的类型与判断的类型有没有父子关系,有则编译通过,否则编译错误
类型转换
类型之间的转换:父 子
子类转换为父类,可能丢失一些方法
小结:
- 父类引用指向子类对象;
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型:强制转换;
- 方便方法的调用,减少重复的代码!简洁
static详解
静态方法里可以调用静态方法,不能调用非静态方法,因为静态方法随着类加载已经加载,而非静态方法还未加载。
静态>匿名>构造
静态代码块:只执行一次
对象一创建先执行匿名代码块,再走构造方法块
匿名代码块常用来赋值初始值(赋初值)
05 抽象类和接口
抽象类
- 正如ADT类型,你描述构造一种类,它是抽象的,再去用代码实现
- abstract,抽象方法,只有方法名字,没有方法的实现。
- 抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类;
- Java的类是单继承的,extends是单继承,但是接口可以多继承
抽象类注意点:
- 不能new出来,只能靠子类去实现它:约束!
- 抽象类中可以写普通方法;
- 抽象方法必须在抽象类中;
- 子类继承父类后,需要通过父类的构造器来实例化,所以抽象类也存在构造器;
抽象的抽象:约束!
接口
锻炼抽象的思维
- 接口中所有定义的方法其实都是抽象的 public abstract,不在方法定义前加修饰符
- 接口中定义的变量都是常量 public static final
- 接口都需要实现类,下面是一个实现类的例子
- 如果要去实现接口里面的所有定义,实现类里面需要对接口的方法全部进行重写
- 接口是可以多继承的,一个实现类可以继承多个接口
- 接口的作用:
- 约束
- 定义一些方法,让不同的人实现
- 方法都是public abstract
- 属性变量都是public static final
- 接口不能别实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须要重写接口的方法
06 内部类及OOP实战
- 通过外部类来实例化内部了
- 内部类直接访问外部类的属性(包括私有属性private)
- 外部类实例化后加载,先加载静态属性,故先实例了内部类,非静态属性未加载,所以在加载内部类时调用了未加载的非静态属性,编译报错,把调用的该非静态属性改为静态就不会编译错误(解决方式之一)
- 一个Java类文件里只能有一个public class类,但是可以有多个class类,但这不是内部类
- 局部内部类,例如定义在方法里的类
拓展
本文地址:https://blog.csdn.net/qq_45000602/article/details/113927165