面向对象
2023-07-24 09:03:42 0 举报
AI智能生成
面向对象基础知识梳理
作者其他创作
大纲/内容
三大特性
封装
概念
封装就是隐藏类的内部信息(属性和方法),不允许外部程序直接访问,而是通过公有的方法才能完成访问(赋值方法get()和取值方法set())
关键字 private(只能本类中访问)
封装属性:私有化属性,提供 无参构造、get和set方法
封装方法:若只需要在本类中调用该方法不希望外部调用,则用private修饰
继承
由来
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,<br>那么多个类无需再定义这些属性和行为,只要继承那一个类即可<br>
关键字 extends
Java对继承的支持性
单继承
不能多继承,可以多层继承
两大特性
单根性
传递性
方法重写<br>
作用
当父类的方法不能满足子类的需求,子类可以重写父类的方法
新增方法/属性
注意点
重写后,子类对象调用的是重写后的方法,不能调用父类的方法<br>而且父类方法也不能被删除,否则报错<br>
方法重写只发生在继承中的子类中<br>
子类中重写的方法,<br>返回值类型,参数名称,参数列表与父类中被重写的方法必须一致。<br>(方法体发生改变,可以修改访问权限:但子类只能扩大权限不能限制权限)<br>
子类和父类同名同参的方法都应该同时是static或非static的<br>static(不是重写)static方法是类的方法,子类无法重写<br>非static可以重写<br>
与方法重载的区别
参数列表
重载:必须修改
重写:可以修改
返回类型
重载:不能修改
重写:可以修改(类型应该是父类方法中返回类型的子类)
访问<br>
重载:可以修改
重写:可以修改,不能做出更严格限制
super关键字
说明
代表父类、超类。用于在子类中访问父类中的属性或者方法
当子类中重写父类的方法时,如果再在子类的方法体中<br>调用父类中的方法,则只能使用super.方法名()
使用区域
只能在子类中使用<br>
作用
在子类中访问父类中的实例变量<br>
在子类中访问父类的实例方法
在子类中访问父类中的构造方法
与 this 关键字的区别
this
描述
代表当前这个对象,也就是:当前谁调用这个方法则this代表的就是谁<br>
使用区域
在当前类(本类)中使用
查找顺序
this关键字访问实例变量或实例变量时,查找顺序:先在当前类中<br>找该实例变量或实例方法,如果找不到则再去父类中找该实例变量或实例方法
super
描述<br>
代表父类/超类<br>
使用区域
只能在子类中使用
查找顺序<br>
直接到父类中查找实例方法或实例变量<br>
因此,得到结论:<br>访问父类中的实例变量或实例方法时,<br>使用super.查找速度相对更快或者执行效率更高。
访问目标
注意点
父类也叫做超类,也叫做基类superclass,子类也叫做派生类subclass<br>
子类继承父类时,没有继承父类的构造方法
子类继承了父类,就继承了父类的方法和属性。
创建子类对象时先默认执行父类的无参构造器( 子类构造方法中默认第一行添加了 super(); )<br>若指定调用父类有参构造需要声明 super(参数)或调用this(···); 此时super()被覆盖<br>
先父后子
super(···)和this(···)不能同时出现在同一构造方法中<br>
<br>
super(···)或this(···)调用语句只能在构造器中的第一句出现<br>
所有类默认继承Object类
多态
概念
多态是指同一行为,通过不同的具体事物,具备多种不同的表现形式。<br>
意义
良好的扩展性(当父类作为方法的参数时可以接收多种子类)<br>
减少代码冗余性
满足条件(三点缺一不可)
继承
重写
父类引用指向子类对象/子类对象赋给父类引用<br>(向上转型)<br>
多态中的动态绑定技术
当构成多态后,引用对象是父类的类型,只能访问父类中公有的属性和方法此时调用<br>该对象的方法显示是父类的,但结果是子类的。<br>(调用方法时会先去父类中查找有没有该方法,无则报编译错误,有则去子类中查找<br>有没有重写的方法,如有则调用子类重写后的方法,如无则使用父类方法。)<br>属性只能调用父类的属性(要想调用子类的属性或独有方法需要向下转型/强制类型转换)<br>
向下转型的注意事项
当构成多态时,父类的引用中存放的是那个子类<br>的对象,则父类的引用就可以转换那个子类类型<br>
在进行向下转型之前,必须先判断,判断被转换的父类的<br>引用与预期要转换的类型是否一致,一致就执行转换操作,反之不执行。
instanceof<br>
使用说明
x instanceof A:检验x是否为类A的对象,返回值为boolean型。<br>
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。<br>
如果x属于类A的子类B,x instanceof A 的值为true。
类型转换<br>
构造方法
是一种特殊的方法 有这些特点<br>
构造方法的名字与类的名字一致
它不声明返回值类型。(与声明为void不同)
不能被static、final、synchronized、abstract、native修饰<br>
不能有return语句返回值<br>
作用<br>
创建对象;初始化对象
分类
有参构造器
无参构造器
注意点
默认存在无参构造,但有参构造会覆盖无参,所以存在有参构造时要显式声明无参构造
构造方法也构成方法的重载
this关键字
代表调用该方法的对象本身(该对象的地址)<br>
访问
访问成员变量(区分成员变量和局部变量)<br>
在同一个类中,局部变量的名字可以和成员变量的名字是可以相同的,不报错,但是局部变量优先,也就是:就近的优先,如果非要访问成员变量,则必须使用this。
访问构造方法
this()无参构造方法<br>
this(参数)有参构造方法
this在构造方法中必须放在第一行
访问实例方法
注意点
<font color="#e0c431">this访问属性和方法时,若在本类中未找到,则去父类中查找</font>
在构造方法中this不能调用自身(会出现递归死循环)
this在构造方法中调用构造方法必须放在首行
首行默认super()若不放在第一行会与super重复调用父类构造方法,出现安全性问题
static<br>
static表示静态的 <br>可以修饰属性、方法、代码块、内部类以及实现静态导入<br>
修饰
全局变量
有static
静态变量/类变量
在类中声明的变量,称为属性或者叫做成员变量、或者叫做字段。<br>那么属性面前如果加入static关键字修饰,称为静态变量,也叫做类的变量。<br>如果属性前面没有编写static关键字,称为实例变量,也叫做对象变量<br>
访问方式<br>
类名.变量名
对象名.变量名<br>
共享数据<br>
类变量由该类的所有实例共享
与实例变量的区别
相同
都是变量<br>
不同
静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。<br>
实例变量对于类的每个实例都有一份,它们之间互不影响。
注意点
当对象名中的值为null时,依然可以访问静态变量名,不会出现空指针异常,<br>原因就是静态变量不属于某一个对象,而是当前这个类的所有对象都可以共享。
静态变量在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,<br>所以静态变量可以使用类名来直接访问,而不需要使用对象来访问。
没有static
实例变量/对象变量<br>
方法<br>
有static
静态方法/类方法
方法前面编写static关键字,称为静态方法,也叫做类的方法。
访问方式
类名.方法名()<br>
对象名.方法名()
注意点
在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。<br>
不能有this关键字<br>
因为不需要实例就可以访问static方法,因此static方法内部不能有this。
不能被重写/继承<br>
没有static
实例方法/对象方法
可以访问<br>
静态变量和静态方法,也可以访问实例变量和实例方法
static关键字实现静态导入<br>
若一个类想直接使用其他类中的静态变量,可以静态导入<br>import static (包名.)类名.静态变量名<br>
static关键字修饰内部类
见内部类--静态内部类
main方法中的static
由于Java虚拟机需要调用类的main()方法,<br>所以该方法的访问权限必须是 public
JVM规定main方法是程序的入口,一般方法都是对象调用的,<br>但在执行main方法前创建对象显然是不可能的,<br>main方法加上static后就解决了该问题,类可以直接调用<br>
该方法接收一个String类型的数组参数,<br>该数组中保存执行Java命令时传递给所运行的类的参数<br>
main() 方法是静态的,我们不能直接访问该类中的非静态成员,<br>必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员<br>
final关键字
描述
final表示最终的<br>
可修饰 类、属性、方法
修饰类
表示该类是最终的(太监类/断子绝孙类),<br>也就是:该类不能再被继承<br>例如:String、Scanner、System<br>
提高安全性和程序的可读性<br>
修饰属性
表示该属性是最终的,也就是:该属性称为常量
注意点
修饰的属性为引用类型属性时,<br>地址不能改变,但地址中的内容可以改变<br>
命名规则:常量习惯用大写命名,若有多个单词,用下划线隔开<br>
一般final关键字与static关键字配合使用<br>
原因:节省空间,在堆内存中只存放一次,<br>并且该类所有对象都可以共享。<br>
被final修饰的成员变量必须被初始化后才能使用
修饰方法
表示该方法是最终的,也就是:该方法不能再被重写
代码块
概念
它用大括号“{}”将多行代码封装在一起,<br>形成一个独立的代码区,这就构成了代码块。
作用
对Java类或对象进行初始化
分类
静态代码块
通常用于初始化静态变量<br>
非静态代码块/匿名代码块
给对象的成员变量初始化赋值,但是因为构造器<br>也能完成这项工作,所以匿名代码块使用的并不多<br>
在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才执行<br>,但是静态变量可以不创建对象而直接使用类名来访问。
执行方式<br>
静态代码块最先执行且只执行一次
匿名代码块在调用构造器时先于构造器执行一次<br>
JVM
大致流程
首先由类装载子系统,将class类文件加载到运行时数据区(JVM内存)中,其次交给执行引擎去执行class文件,然后进行GC垃圾回收。<br>
类装载子系统
<font color="#e74f4c">有三种类装载器(待完善)</font>
运行时数据区(内存)
<font color="#f2f2f2">分为五个区域</font><br>
虚拟机栈<br>
Java虚拟机栈 Java Virtual Machine Stack,早期也叫Java栈,简称栈,主管Java程序的运行,它保存方法的局部变量、并参与方法的调用和返回。<br>
入栈/压栈
出栈/弹栈
栈帧<br>
存放方法的 参数 和 局部变量等<br>
堆(heap)<br>
JVM内存最大的一块区域
存放对象实例(属性及其数据)<br>
执行new关键字时就会在堆中开辟新的空间<br>
方法区(Method Area)
存储已被虚拟机加载的class信息。<br>
类加载器将class文件加载到内存之后,将类的信息存储到方法区中。
存储内容
类型信息
① 这个类型的全限定名(包名.类名)<br>
② 这个类型直接父类的全限定名<br>
③ 这个类型的修饰符( public, abstract,final)<br>
域信息<br>
属性名称、属性的类型
方法内容
方法名称、方法的返回类型
方法参数的数量和类型<br>
程序计数器(Project Counter Register)
记录字节码指令执行的位置<br>
本地方法栈(Native Method Stack)
局部变量:<br>
在方法内部声明,使用之前,必须初始化;存储在栈中,一旦方法使用完,变量就失效。
成员变量(属性):<br>
定义在类中,方法外,有默认值,存在堆中,对象使用完毕,就被gc()回收。<br>
作用
将class文件加载到内存中
执行引擎
作用
Java字节码的执行是由JVM 执行引擎来完成。
本地接口库
作用
Java源码中Native 方法 就是典型的本地方法接口,作用就是融合不同的编程语言为Java所用,它的初衷是融合C/C++程序。
程序设计思想
面向过程<br>
强调步骤<br>
面向对象
强调对象
设计模式
概念
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 <br>以及解决问题的思考方式。设计模式免去我们自己再思考和摸索。就像是经典 <br>的棋谱,不同的棋局,我们用不同的棋谱。”套路”<br>
分类
单例设计模式
概念
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对 <br>某个类只能存在一个对象实例,并且该类只提供<font color="#e0c431">一个</font>取得其对象实例的方法。<br>
实现
方式一:饿汉式
1.私有化构造器
2.内部提供一个当前类的实例(已初始化)(且为静态的)<br>
3.提供公共的静态方法,返回当前类的实例<br>
方式二:懒汉式
与方式大致相同,不同的是提供的实例未初始化,<br>当需要用到的时候(调用返回实例的方法)再初始化<br>
目前还存在线程安全问题<font color="#e74f4c">(未完善)</font>
优点
减少系统性能开销<br>
应用场景
网站的计数器<br>
应用程序的日志应用<br>
数据库连接池<br>
读取配置文件的类<br>
等等....
模板方法设计模式<br>
概念
当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以 <br>把不确定的部分暴露出去,让子类去实现。<br>
代理设计模式<br>
概念
可以为其它对象提供一种代理以控制对这个对象的访问,屏蔽对真实角色的直接访问。<br>
分类
静态代理(静态生成代理类)
动态代理(动态生成代理类)<font color="#e74f4c">(未完善)</font>
工厂设计模式<font color="#e74f4c">(未完善)</font>
本质思想
实例化对象,用工厂方法代替 new 操作。 <br>将选择实现类、创建对象统一管理和控制。<br>从而将调用者跟我们的实现类(实际要new的类)解耦。<br>
分类
简单工厂模式
作用<br>
简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,<br>通过接收的参数的不同来返回不同的实例对象。<br>
缺点
对于增加新产品,不修改代码的话,是无法扩展的。<br>违反了开闭原则(对扩展开放;对修改封闭)
工厂方法模式
抽象工厂模式<br>
类与对象
类
概念:是对一类事物的描述,是抽象的。<br>
包含
行为(方法)
属性
内部类<br>
概念
当一个类的定义出现在另一个类的<font color="#e0c431">类体中</font>时,那么这个类叫做内部类,而这个类所在的类叫做外部类。<br>
注意:内部类不是在一个Java源文件中编写俩个平行的两个类,而是在一个类的内部再定义另外一个类。
意义
可让类和类之间的继承/实现更简化<br>
让接口和抽象类也可以new
使用场景
当一个类存在的价值仅仅是为某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,<br>这样可以隐藏该类的实现细节并且可以方便的访问外部类的私有成员而不再需要提供公有的get和set方法。<br>
分类
成员内部类<br>
概念
直接将一个类的定义放在另外一个类的类体中。<br>
分类
非静态内部类
解读<br>
在A类中申明了一个B类,此B类就在A的内部,并且在成员变量的位置上,<br>所以就称为成员内部类,由于此时的内部类没加static,所以叫做非静态内部类。
使用方式
<br>
静态内部类
匿名内部类
抽象类
描述
被abstract关键字修饰的类就抽象类<br>
关键字:abstract
表示抽象
包含
普通方法
抽象方法
不能有方法体
只能存在抽象类中
没有重写全部抽象方法的仍然是抽象类
属性
注意
抽象类不能被实例化,但可以通过子类创建对象(多态)(向上转型)<br>
父类中的抽象方法虽然没有被子类直接使用,但也不能删除,<br>否则子类无法重写该抽象方法。<br>
可以定义构造器(因为被继承后需要加载子类属性和构造方法)<br>
本质<br>
父类提供抽象方法,交由子类进行具体实现<br>
接口(特殊的抽象类)
概念:Java中的接口就是一种统一了实现子类的开发标准。<br>但凡符合接口标准的子类都可以和接口做适配。<br>
关键字 interface
表示接口
实现:implements<br>
语法格式:先写extends在写implements<br>
本质
将功能封装——解耦
注意点
接口是抽象方法和常量定义的集合(JDK7及之前)
所有成员变量默认被 public static final 修饰<br>
抽象方法默认被 public abstract修饰<br>
没有重写全部方法可以作为一个抽象类
多继承(多实现)的机制,弥补了java单继承的不足
一个类可以实现多个接口,接口也可以继承多个接口<br>(类不能多继承是因为当两父类出现同名方法,<br>子类不知道继承哪个)(接口可以多继承,因为接口中都是<br>抽象方法,继承哪个方法都无所谓)<br>
<font color="#e0c431">没有构造器</font>
不能被实例化,但可以通过子类创建对象,和继承关系类似,也是多态的一种形式<br>
jdk9中可以有私有方法
JDK8中接口的改进
<br>
接口中的默认方法<br>
当两个接口的默认方法同名由都被同一个类实现时,会出现<font color="#f1e4a2">接口冲突</font>问题<br>子类应该指明调用哪一个方法:类名.super.方法名()<br>
抽象类与接口异同
相同点
都不能创建对象,其实:抽象类和接口都是多态的一种形式<br>
抽象类和接口中都可以编写抽象方法<br>
子类或实现类都必须要重写抽象类或接口中的所有的抽象方法,否则子类或实现类就是抽象类<br>
不同点
关键字不同
结构不同
抽象类除了有有普通类所有内容,还有抽象方法<br>
接口不同JDK版本内容不一样,JDK7及之前只有抽象方法和常量<br>JDK8新增静态方法和默认方法,JDK9新增私有方法等<br>
抽象类要被继承(单继承),接口要被实现(可以多实现)<br>
<font color="#e0c431">继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。<br>如果一个类继承了某个抽象类,则子类必定是这个抽象类的种类,<br>而接口实现则是有没有、具备不具备的关系</font><br>
子主题<br>
对象
概念:是一类事物的实例,是具体的。<br>
Object类
概述<br>
Object类是所有Java类的根父类<br>
如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类<br>
主要方法
<br>
疑问:为何调用方法时会出现Object类中的方法?
说明
当一个类继承另一个类后,子类对象调用方法会现在子类<br>中查找该方法,若找不到再去父类中查找<br>
当某方法只在父类中定义时,调用该方法会使用父类的属性<br>若该方法又调用了其他的方法,那么还是按照上面的顺序,<br>先从子类查找,找不到再去父类中查找。<br>
经典面试题:==操作符和equals方法的区别<br>
==
基本类型比较<br>
比较两个变量的值,相等则返回true<br>
引用类型比较
比较两个引用的地址是否相等,相等则返回true<br>
equals()方法<br>
不能比较基本数据类型
未重写时
引用类型比较
比较两个引用的内存空间地址是否相等,相等则返回true<br>( 和 == 作用一致,源码中就是用==判断的)<br>
被子类重写
当用equals()方法进行比较时,对类File、String、Date及包装类 <br>(Wrapper Class)来说,是比较类型及内容而不考虑引用是否是同一个对象;<br>
String类重写
作用
比较字符串是否相同,<br>相同为true,不同为false<br>
源码解读
先比较地址是否相同,相同直接返回true<br>不同再看传进来的参数 instanceof String<br>先强制转换成String类型<br>再看长度是否相同,不同直接返回false,<br>相同再将字符串转换成数组取出每一个比较,<br>都相同返回true<br>
参数为null时结果为false
补充:String类创建对象的两种方式
①String 引用名=“xx”;(字面量)<br>
方式①创建的对象只要等号右边的一样,就指向同一地址(常量池)
字符串常量池中只存储String类型,且存放的是String对象的引用而不是内容
举例:当执行 String a=“hello”;时,jvm会先在堆内存中找有没有“hello”,有则将该引用赋值给 a<br>没有则在堆中新建一块内存,并将新的引用驻留在常量池中
②String 引用名=new String(“xxx”);
方式②是创建的对象指向不同的地址 但若xxx内容相同 用equals方法也会返回true(比较值)<br>(执行new关键字就会在堆中开辟新的内存空间)
注意事项
使用equals方法时尽量把未知的变量放在括号中<br>这样就算变量为null也不会报错,若放在前面 为null时,<br>就会报空指针异常NullPointException
toString()方法
概述
toString()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址。<br>
在进行String与其它类型数据的拼接操作时,自动调用toString()方法
重写
重写后就是以字符串形式打印对象的属性<br>
作用<br>
快速展示类中的属性
包装类
概述
针对八种基本数据类型定义相应的引用类型—包装类(封装类)<br>有了类的特点,就可以调用类中的方法,Java才是真正的面向对象<br>
基本类型对应包装类
作用
数据转换<br>
数据类型转换
大小写转换
常用方法
byte byteValue()
作用
把包装类对象转换为byte字节
说明
所有的包装类底层都有一个value属性 保存对应的基本类型数据, <br>byteValue()方法底层就是把value属性强制转换为byte字节类型<br>
注意:byte类型范围为 -128-127 超过范围的会被缩小
static int compare(int x, int y)<br>
作用
比较两个基本类型数据的大小,如果前面的数大返回正数, 后面的数大返回负数, 相等返回0<br>
例
Integer.compare(10, 20)<br>
-1
Double.compare(8,4.5)<br>
1
Character.compare('A', 'b')<br>
-33(ASCII码差值)
Boolean.compare(false, true)<br>
-1(true比false大)
int compareTo(Integer anotherInteger)
作用
比较两个包装类对象的大小<br>
说明
所有的包装类都实现了Comparable接口, 重写了compareTo()方法, <br>包装类对象比较大小时, 其实就是比较它的value属性值 的大小
例
i1.compareTo(i2)<br>
static int parseInt(String s)
把字符串转换为int整数
Character没有 parseXxx方法<br>
提供静态方法创建包装类对象<br>
从JDK9开始, 包装类的构造方法都使用@deprecated注解修饰为已弃用, 已过时, <br>即从JDK9开始,不建议使用构造方法创建包装类对象了,<br>再使用构造方法时会在方法中间添加一条横线表示已弃用, 建议使用静态方法valueOf()创建<br>
例
static Integer valueOf(int i)
static Integer valueOf(String s)
Integer.valueOf("852")<br>同样字符串要符合对应的数字格式<br>
拆装箱
装箱
由基本类型到包装类型<br>
由小到大
自动数据类型转换
例:Integer i1 = 789; //自动装箱
例题: Integer i3 = 69;<br> Integer i4 = 69;<br> System.out.println(i3 == i4);<br>结果为true
说明:Java认为-128~127范围内的整数使用最频繁,<br> 所以这个范围内整数自动装箱后, 采用享元模式, 类似<br>于String字符串字面量,即i3与i4引用的是共享池中<br>同一个value值为69的Integer对象<br>
拆箱
由包装类型到基本类型
由大到小
强制类型转换<br>
例:int num = i1; //自动拆箱<br>
访问权限修饰符
作用
Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。
四种访问权限修饰符
0 条评论
下一页