类的总结-封装、继承、多态
0.封装
定义:利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内部的细节,但可以通过对象对外提供的接口来访问该对象。
优点
1.减少耦合: 可以独立地开发、测试、优化、使用、理解和修改
2.减轻维护的负担: 可以更容易被程序员理解,并且在调试的时候可以不影响其他模块
3.有效地调节性能: 可以通过剖析确定哪些模块影响了系统的性能
4.提高软件的可重用性
5.降低了构建大型系统的风险: 即使整个系统不可用,但是这些独立的模块却有可能是可用的
1.方法重写
方法的重写(override/overwirte)
1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中同名参数的方法时,实际执行的是子类重写父类的方法
3.重写的规定:
方法的声明:权限修饰符 返回值类型 方法名(形参列表){
//方法体
}
约定俗称:子类中的重写的方法,父类中的叫被重写的方法
1.子类重写的方法的方法名和形参列表与父类被重写 方法的方法名和形参列表相同
2.子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
>特殊情况:子类不能重写父类中声明为private权限的方法
3.返回值类型:
>父类被重写的方法的返回值类型void,则子类重写的方法的返回值类型只能是void
>父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
>父类被重写的方法的返回值类型是基本数据类型(比如:int),则子类重写的方法的返回值类型必须是相同的
4.子类重写的方法抛出异常类型不大于父类被重写的方法抛出的异常类型
----------------------------------------------------------------
*子类和父类中同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写也不能被重写)
2.方法的重载
重载的概念:
在不同类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可.
重载的特点:
1.与返回值类型无关.
2.只看参数列表,且参数列表必须不同.(参数个数或者参数类型)
3.调用时,根据方法参数列表的不同来区别
示例:
int add(int x,int y){
return x+y;
}
int add(int x,int y,int z){
return x+y+c;
}
double add(double x,double y){
return x+y;
}
3可变个数的形参
1.声明格式:方法名(参数的类型名...参数名)
2.可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
3.可变参数形参的方法与同名方法之间,彼此构成重载
4.可变参数方法的使用与方法参数部分使用数组是一致的
5.方法的参数部分有可变形参,需要放在形参声明的最后
6.在一个方法的形参位置,最多只能声明一个可变个数形参
4.修饰符(封装,和隐藏)
public 同一个工程
protected 不同包的子类
default 同一个包
private 类内部
5.构造器
1.构造器的特征
1.它具有与类相同的名称
2.它不声明返回值类型.(与声明为void不同)
3.不能被static,fianl,synchronized,abstract,native修饰,不能有return语句返回值
格式
修饰符 类名(参数列表){
初始化语句;
}
2.根据参数不同,构造器可以分为如下两类:
1.隐式无参构造器(系统默认提供)
2.显示定义一个或多个构造器(无参,有参)
注意:
1.java语言中,每个类都至少有一个构造器
2.默认构造器的修饰符与属类的修饰符一致
3.一旦显示定义了构造器,则系统不再提供默认构造器
4.一个类可以创建多个重载的构造器
5.父类的构造器不可被子类继承
6. this关键字
this关键字的使用
1.this理解为:当前类
2.this可以用来调用:属性,方法,构造器
3.this的使用
1.在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性,不过,通常我们都习惯省略this.
2.当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明改变量是类的成员变量.
例 public person(String name,int age){
this.name=name;
this.age=age;
}
3.使用this访问属性和方法时,如果在本类中未找到,会从父类中查找
4.this可以作为一个类中构造器相互调用的特殊格式
注意:
1.可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其它构造器
2.构造器中不能通过"this(形参列表)"的方式调用自身构造器
3.如果一个类中声明了n个构造器,则最多有n-1个构造器中使用"this(形参列表)"
4."this(形参列表)"必须声明在类的构造器的首行
5.在类的一个构造器中,最多只能声明一个"this(形参列表)"
7.super关键字
super关键字的使用
1.super理解为:父类的
2.super可以用来调用:属性,方法,构造器
3.super的使用
1.我们可以在子类的方法或构造器中.通过使用"super.属性"或"super.方法"的方式,显示的调用父类中声明的属性或方法.但是,通常情况下,我们习惯省略"super."
2.特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须使用"super.属性"的方式,表明调用的是父类中声明的属性.
3.特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显示使用"super.方法"的方式,表明调用的是父类中被重写的方法.
4.super调用构造器
1.我们可以在子类的构造器中显示的使用"super(形参列表)"的方式,调用父类中声明的指定构造器
2."super(形参列表)"的使用,必须声明在子类构造器的首行
3.我们再类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
4.在构造器的首行,没有显示声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super();
5.在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类的构造器
8. 关键字package
package语句作为java源文件的第一条语句,指明该文件中定义的类所在的包.(若default该语句,则指定为无名包)
格式为:package 顶层包名.子包名;
规范:
1.包对应于文件系统的目录,package语句中,用"."来指明包(目录)的层次
2.包通常用小写单词标识.通常使用所在公司域名的倒置:com.wei.xxx
包的作用:
1.包帮助管理大型软件系统:将功能相近的类划分到同一个包中.比如:MVC的设计模式
2.包可以包含类的子包,划分项目层次,便于管理
3.解决类命名冲突的问题
4.控制访问权限
9.import关键字
为使用定义在不同包中的java类,需要import语句来引入指定包层次下所需要的类或全部类(.*)
**import语句告诉编译器到哪里去寻找类
语法格式
import 包名.类名;
注意:
1. 在源文件中使用import显式的导入指定包下的类或接口
2. 声明在包的声明和类的声明之间。
3. 如果需要导入多个类或接口,那么就并列显式多个import语句即可
4. 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
5. 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
6. 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
是哪个类。
7. 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
8. import static组合的使用:调用指定类或接口下的静态的属性或方法
10.继承
作用
1.继承的出现减少了代码冗余,提高了代码的复用性.
2.继承的出现,更有利于功能的扩展.
3.继承的出现让类与类之间产生了关系,提供了多态的前提
>不要仅为了获取其它类中某个功能而去继承,因遵循一个 is a 关系
使用
1.在java中,继承的关键字用的是"extends",即子类不是父类的子集而是对父类的扩展.
规则
1.子类不能直接访问父类中私有的private的成员变量和方法.
2.java只支持单继承和多层继承,不允许多重继承
一个子类只能有一个父类
一个父类可以派生出多个子类
12.子类对象实例化的全过程
1.从结果上来看:(继承性)
子类继承父类以后,就获取了父类中声明的属性或方法
创建子类对象,在堆空间中,就会加载所有父类中声明的属性
2.从过程上来看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,直到调用了java.lang.Objext类中空参的构造器为止.正因为加载过所有的父类的结构,所有才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用.
13.多态
多态性:
1.理解多态性:可以理解为一个事物的多种形态.
2.何为多态性:
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
例:person p= new Man()
3.多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法(动态绑定).
总结:编译-看左边
运行-看右边
4.多态性的使用前提:
1.要有类的继承关系
2.要有方法的重写
5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
14.instanceof关键字的使用
a instanceof 判断对象A是否是类A的实例.如果是,返回trur;如果不是,返回false.
使用情景:为了避免在向下转型时出现ClassCsetException的异常,我们在向下转型之前,先进行instanceof的判断,一但返回true,就进行向下转型.如果返回false,不进行向下转型
如果a instanceof A返回true,则a instanceof B也返回true.其中类B是类A的父类.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpb8Y4Q9-1638087380744)(C:\Users\WLW\AppData\Roaming\Typora\typora-user-images\image-20211117193040838.png)]
15.java.lang.object类
1.Object类是所有java类的根父类
2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
3.Object类中的功能(属性,方法)具有通用性
属性:无
方法:equals()/ toString()/getClass()/hashCode()/clone()/finalize()/
wait(),notify(),notifAll()
4.Object类只声明了一个空参的构造器
16.==
面试题:==和equals()的区别
一.回顾==的使用
1.可以使用在基本数据类型变量和引用数据类型变量中
2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等(不一定类型要相同)布尔类型除外
如果比较的是引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
补充:==符号使用时,必须保证符号左右两边的变量类型一致
二.equals()方法的使用;
1.是一个方法,而非运算符
2.只能适用于引用数据类型
3.Object类中的equals()定义:
public boolean equals(Object obj){
return (this == Object);
}
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同,即是否指向同一个地址值;
4.像String,Date,File,包装类等都重写了Object类中的equals()方法.重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同.
5.通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同.那么我们就需要对Object类中的equals()进行重写.
17.toString
object类中toString()的使用
1,当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
2.Object类中toSting()定义;
public String toString(){
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
3.像String,Date,File,包装类等都重写了Object类中的toString()方法.
使得在调用对象的toString()时,返回"实体内容"信息
18.java中的JUnit单元测试
1.选中当前工程-右键选择:build path-add libraries-Junit 4 - 下一步
2.创建java类,进行单元测试.
此时的java类要求:
1.此类是public的
2.此类提供公共的无参的构造器
3.此类中声明单元测试方法.
此时的单元测试方法:方法的权限是public,没有返回值,没有形参
4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入,import org.junit.Test
5.声明好单元测试方法以后,就可以在方法体内测试相关代码.
6.写完代码以后,左键双击单元测试方法名,右键:run as-Junit Test
说明:
1.如果执行结果没有任何异常:绿条
2.如果执行结果出现异常:红条
19.包装类的使用
包装类的使用:
1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
2.掌握的:基本数据类型,包装类,String三者之间的相互转换
基本数据类型--->包装类,调用包装类的构造器
包装类--->基本数据类型:调用包装类XXX的xxxValue()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ph0CddWD-1638087380746)(C:\Users\WLW\AppData\Roaming\Typora\typora-user-images\image-20211118200200372.png)]
20.包装类的使用
装箱
通过包装类的构造器实现
int i =500;
INtrger t=new Integer(i);
拆箱
调用包装类的.xxxValue
boolean b=bobj.booleanValue();
字符串转换成基本数据类型
通过包装类的构造器实现
int i=new Integer("12");
通过包装类的parsexx(String s)静态方法
基本数据类型转换成字符串
调用字符串重载的valueOf()方法;
21.抽象类
1.抽象类不能直接实例化.
2.抽象方法不能是private
3.抽象类中可以包含其他的非抽象方法,也可以包含字段,这个非抽线方法和普通方法的规则都是一样的,可以被重写,也可以被子类直接调用
abstract关键字的使用
1.abstract:抽象的
2.abstract可以用来修饰结构:类方法
3.abstract修饰类:抽象类
>此类不能实例化
>抽象类中一定有构造器,便于子类实例化时调用
>开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作
4.abstrct修饰方法:抽象方法:抽象方
>抽象方法只有方法的声明,没有方法体
>包含抽象方法的类,一定是一个抽象类,反之,抽象类中不一定要有抽象方法
>若子类重写了父类中的所有的抽象方法,此类方可实例化
若子类没有重写了父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstrct修饰
abstract使用注意点
1.abstrct不能用来修饰:属性,构造器等结构
2.abstrct不能用来修饰:private方法,静态方法,final的方法,fianl的类
23.接口 interface
1.使用interface
2.接口中方法一定是抽像方法,因此可以省略abstract
3.接口中方法一个是public,因此可以省略public
3.使用implement继承接口,此时表达的含义不在是"扩展",而是"实现"
4.在调用的时候同样可以创建一个接口的引用,对应到一个子类的实例
5.接口不能单独被实例化
接口的使用
1.接口使用interface来定义
2.java中接口和类是并列的两个结构
3.如何定义接口:定义接口中的成员
3.1 JDK及以前:只能定义全局常量和抽象方法
>全局变量:public static fianl的,但是书写时,可以省略不写
>抽象方法:public abstract的
3.2JDK8:除了定义全局变量和抽象方法之外,还可以定义静态方法,默认方法
4.接口中不能定义构造器的?意味着接口不能实例化
5.Java开发中,接口通过让类去实现(implement)的方式来使用
如果实现类覆盖了接口中所有的抽象方法,则此实现类就可以实例化
如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍是一个抽象类
6.java类可以实现多个接口--->弥补Java的单继承的局限性
格式class AA extends BB implements CC,DD,EE
7.接口与接口之间可以实现多继承
**************************************************
8.接口的具体使用,体现多态性
9.接口,实际上可以看做是一种规范
10.接口中的普通方法,不能有具体的实现.非要实现,只能通过关键字default来修饰,这个方法
11.接口里所有方法都是public的
接口的使用
1.接口使用上也满足多态性
2.接口,实际上就是定义了一种规范
3.开发中,体会面向接口编程
24.static关键字的使用
1.static:静态的
2.static可以用来修饰:属性,方法,代码块,内部类
3.使用static修饰属性:静态变量(或类变量)
3.1属性:按是否使用static修饰,有分为:静态属性vs非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性.当修改其 中一个对象中的非静态属性时,不会导致其他对象中同样的属性值修改
静态变量:我们创建了类的多个对象,多个对象共享一个静态变量.当通过某一个对象修改静态 变量时,会导致其它对象调用此静态变量时,是修改过了的.
3.2static修饰属性的其它说明:
1.静态变量随着类的加载而加载.可以通过"类.静态变量"的方式进行调用
2.静态变量的加载要早于对象的创建.
3.由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中.
4 类变量 实例变量
类 yes no
对象 yes yes
3.3静态属性举例:System.out;Math.PI;
4.使用static修饰符方法:静态方法
1.随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
2. 类变量 实例变量
类 yes no
对象 yes yes
3.静态方法中,只能调用静态的方法或属性(根据生命周期来理解)
非静态方法中,即可以调用非静态的方法或属性,也可以调用静态的方法或属性.
5.static注意:
5.1在静态的方法内,不能使用this关键字,super关键字
5.2关于静态属性和静态方法的使用 (从生命周期的角度去理解)
6.开发中,如何确定一个属性是否要声明为static的?
>属性是可以被多个对象所共享的,不会随着对象的不同而不同
>类中的常量也常常声明为static
开发中,如何确定一个方法是否要声明为static的?
>操作静态属性的方法,通常设置为static的
>工具类中的方法,习惯上声明为static的,比如Math,Arrays.Collections
25.单例设计模式
单例设计模式:
1.所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例
2.如何实现?
饿汉式
1.私有化的构造器
private Bank(){
}
2.内部创建类的对象
4.要求此对象也必须声明为静态的
private static Bank instance=new Bank();
3.提供公共的静态的方法,放回类的对象
public static Bank getInstance(){
return instance;
}
懒汉式
1.私有化的构造器
private Order(){
}
2.内部创建类的对象
4.要求此对象也必须声明为静态的
private static Order instance=null;
3.提供公共的静态的方法,放回类的对象
public static Bank getInstance(){
if(instance==null)instance = new Order();
return instance;
}
3.区分饿汉式和懒汉式
饿汉式:坏处 对象加载时间过长
好处 饿汉式是线程安全的
懒汉式:好处 延迟对象的创建
坏处 线程不安全
26.类中代码结构的使用
1.代码块的作用:用来初始化类,对象
2.代码块如果有修饰的话,只能使用static
3.分类:静态代码块 vs 非静态代码块
4.静态代码块
>内部可以有输出语句
>随着类的加载而执行,而且只执行一次
>作用:初始化了的信息
>如果一个类中定义了多个静态代码块,则按照声明的先后顺序来执行
>静态代码块的执行要优先于非静态代码块的执行
>静态代码块内只能调用静态的属性,静态的方法,不能调用非静态的结构
5.非静态代码块
>内部可以有输出语句
>随着对象的创建而执行,
>每创建一个对象,就执行一次代码块
>作用:可以在创建对象时,对对像的属性等进行初始化
>如果一个类中定义了多个非静态代码块,则按照声明的先后顺序来执行
>非静态代码块内可以调用静态的属性,静态的方法,或非静态的属性,非静态的方法
27.对属性可以赋值的位置
1.默认初始化
2.显示初始化/5在代码块中赋值(并列)
3.构造器中初始化
4.有了对象以后,可以通过:"对象.属性"或"对象.方法"的方式,进行赋值
28.fianl
1.final可以用来修饰的结构:类,方法,属性
2.final 用来修饰一个类:此类不能被其它类所继承
比如:String类,System类,StringBuffer类
3.fianl 用来修饰方法:表明此方法不可以被重写
比如:Object类中getClass();
4.fianl用来修饰变量:此时的"变量"就称为是一个常量
4.1fianl修饰属性:可以考虑赋值的位置有:显示初始化代码块中初始化,构造器中初始化
4.2final修饰局部变量:
使用fianl修饰形参时,表明此形参是一个常量.当我们调用此方法是,给常量形参赋一个实参,.一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值
static fianl 用来修饰属性:全局变量