Java面向对象
2022-08-23 17:17:40 2 举报
AI智能生成
Java面向对象知识汇总
作者其他创作
大纲/内容
相关面试题
方法的重写和重载的区分?
override / overwrite / overload;
谈谈对多态的理解?
== 和 equals()区别?
throws 和 throw 的区别?
接口与抽象类的区别?
Object类
使用说明:
① Object是所有其他类的根父类;
② Object类中只定义了一个Object();
③ Object类中定义的方法适用于任何其子类,包括数组;
equals():
① java.lang.Object类中的equals()方法的定义:
public boolean equals(Object obj) {
return (this == obj);
}
② 像String、Date、File、包装类等重写了Object类中的equals()方法,比较两个对象中的实体内容是否相等;
③ 对于自定义类来讲,如果没重写Object类中的equals()方法,调用equals()方法时,仍然比较两个对象的引用地址是否相同;
④ 一般情况下,在开发中一旦调用了自定义类的equals(),通常都是重写以后的equals()方法;
⑤ 重写equals()的规则:比较两个对象的属性是否都相等;
toString():
① java.lang.Object类中toString()定义如下:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
② 当我们打印一个对象的引用时,实际上就是调用了其toString();
③ 像String、Date、File、包装类等重写了Object类中的toString(),返回其代表的具体内容;
④ 对于自定义类而言,如果我们没有重写Object类中的toString()方法,则返回的仍然是地址值;
⑤ 如果重写的话,重写的规则:返回当前对象的属性信息;
类及类的成员
属性
变量的分类:
成员变量:
实例变量
先声明,后使用;
实例变量有其所在的一个作用域{},只有在其定义的作用域中有效;
随着对象的创建而产生,分配在堆空间;
可以采用默认初始化,也可以采用其他方式进行初始化;
每个对象均拥有一份实例变量,通过 对象.属性 修改此实例变量;
可以声明权限修饰符;修饰符有:public 、缺省 、protected、private ;
类变量
采用static关键词修饰;
采用类名 . 类变量的方法调用;
随着类的加载而产生,分配在方法区,类变量早于方法的创建;
类变量为类的所有对象共享,一经改变,后续调用为改变后的值;
局部变量:
局部变量声明在:方法体中、方法的形参、内部类、代码块、构造器(构造器的形参);
局部变量也需要先声明赋值,后使用,也可采用默认的初始化值。注意:方法的形参为特殊,它的初始化为方法调用时传入的值;
局部变量没有权限修饰符,它的权限跟随方法,或者构造器的权限;
局部变量存放在栈空间;
属性的声明格式:
修饰符 数据类型 变量名(xxYy) = 初始化值 ;
接口中,常量的声明格式 :public static final 数据类型 = 变量名(XXYY) = 初始化值;
对属性的赋值操作:
① 默认初始化 --> ②显式初始化 / ③ 代码块初始化-->④ 构造器初始化 -->⑤ 变量名. 方法 或者 变量名. 属性
方法
方法的声明格式:
权限修饰符:public protected 缺省 private;
返回值类型:
没有返回值:采用void 关键字;
具体的返回值类型:如果方法有返回值,那么方法中一定有return;
方法名:属于标识符。需要命名时,满足标识符的命名规则和规范,"见名知意“;
形参列表:可以声明0个,1个或多个变量。如果声明了多个变量,中间用","隔开;
方法体:调用方法时,要执行的逻辑;
方法中可以声明内部类;注意:方法中不可以定义新的方法;
在继承的基础上,方法可以重载和重写:
方法的重写
重写的定义:
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法;
重写的要求:
① 重写方法必须和被重写方法具有相同的方法名称、参数列表;
② 重写的方法的返回值类型不能大于被重写的方法的返回值类型;
③ 重写方法使用的访问权限不能小于被重写方法的访问权限;
④ 子类方法抛出的异常不能大于父类被重写方法的异常;
注意:① 子父类中同名的方法(非重写)须同时为 static 的,或同时为非 static 的;② 子类不能重写父类中声明为 private 权限的方法;
方法的重载
重载的定义:
在同一个类中定义多个同名的方法,且参数不同;
重载的要求:
① 方法名相同,参数列表不同;
② 参数列表顺序不同,或返回值类型不同;
对于重载而言,方法调用之前,编译器已确定所要调用
方法的递归:
① 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制;
② 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环;
方法的值传递:
① 如果方法的形参是基本数据类型的变量,则方法调用时,传递的实参即为基本数据类型变量所保存的具体的数值;
② 如果方法的形参是引用数据类型的变量,则方法调用时,传递的实参即为引用数据类型变量所保存的地址值;
方法的调用:
① 方法中可以调用属性、方法;
② 静态的方法只能调用静态的方法和属性;非静态的方法可以调用静态的方法和属性也可以调用非静态的方法和属性;
构造器
构造器的声明格式:
① 权限修饰符 类名 (参数){构造器的执行语句(此可有可无)} 注意:可以声明无参的构造器;
② ①构造器都会默认的声明super关键字,调用父类的构造器,不显示的声明,则程序会自动的调用Object类的无参构造器;
③ 不显示的声明构造器,系统会提供一个无参的构造器,一旦显式声明构造器,系统将不再提供无参的构造器;
构造器的作用:
创建类的对象;
初始化对象的属性;
构造器彼此之间可以实现重载;
注意:抽象类中也有构造器,但是,抽象类中的构造器不能实例化,是为了让子类继承时调用;
代码块
代码块的格式:
{} 非静态代码块
static{} 静态代码块
代码块的作用:用来初始化类、对象的信息;
代码块的分类:
静态代码块:
① 随着对象的创建而执行,可以提供输出语句。
② 作用:初始化类的加载信息;
③ 内部只能调用当前类中静态的属性、方法。不能调用非静态的属性、方法;
④ 如果定义了多个静态代码块,照定义的先后顺序执行;
⑤ 静态代码块的执行要早于非静态代码块;
⑥ 随着类的加载而执行,且只被加载一次;
非静态代码块:
① 随着对象的创建而执行;
② 每创建一个对象,都会执行一次;
③ 作用:用来初始化对象的属性信息;
④ 可以调用当前类的方法和属性;
相同点:
均可以有输出语句;
如果定义了多个静态或者非静态代码块,照定义的先后顺序执行;
内部类
内部类的定义:
java 语言在一个类A的内部再定义另外一个类B; A为外部类 B 为内部类;
内部类的分类:
成员内部类
静态成员内部类
非静态成员内部类
局部内部类
java8 新特征
① 需要显式的声明为final;
② java8中可以省略final的声明;
内部类,作为一个类:
① 内部里可以定义属性、方法、构造器;
② 内部类可以被 final 、abstract 关键字修饰;
内部类作为外部类的成员:
① 可以被4种不同的权限修饰;
② 可以被 static 修饰;
③ 可以调用外部类的结构:属性、方法等;
需掌握知识点:
如何创建成员内部类的对象?
如何调用外部类的结构?
面向对象三大特征
封装性
封装性的体现:
狭义上体现:
① 私有化(private)类的属性xxx,同时,提供公共的(public)设置(setXxx())和获取(getXxx())的方法;
② 如果类中的方法,不希望在类外被调用,我们可以设置为 private 的;
③ 如果类A不希望在本包之外被调用,那么可以将此类A声明为缺省的;
④ 单例模式
饿汉模式;
懒汉模式;
广义上体现:
① java规定的4种权限修饰:(从小到大) private 缺省 protected public;
② java规定的4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类;
③ 4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类;注意:只能使用缺省 或者 public 来修饰类 ;
四种权限修饰符:
从大到小:
private < 缺省 < protected < public;
权限修饰符可修饰的结构:
① 4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类;
② 只能使用缺省 或者 public 来修饰类 ;
修饰范围:
继承性
继承的体现
为什么有继承:
多个类中存在相同属性和行为时,将这些内容抽象为一个类;
继承的格式:
class A extends B 其中:A 为子类 B 为父类又名基类、超类
继承性说明:
① 子类和父类是相对的概念,父类又继承自己的父类,所有的类直接或间接的继承 lang 包下的 Object 类;
② 子类通过继承,可以获取直接父类以及所的间接父类中声明的所的属性和方法;
③ 一个父类可以有多个子类,但子类只能声明一个父类;
④ 如果一个类没有显式继承另外一个类的话,则其父类为:java.lang.Object类(根基类);
⑤ 任何一个类在继承java.lang.Object类之后,就获取了 Object 类中声明的属性和方法;
⑥ java 中,继承是对父类的扩展,而不是父类的子集;
继承的作用:
① 减少了代码的冗余,提高了复用性;
② 具有更好的扩展性,继承的出现让类与类之间产生了关系,提供了多态出现的前提;
⚠️不要仅为了获取其他类中某个功能而去继承;
继承的规则:
注意:子类不能直接访问父类中私有的(private)的成员变量和方法;
类的继承
子类继承父类后的不同:
① 子类A继承父类B以后,就获取了父类中声明的结构:属性、方法;
② 子类不能直接访问父类中私有成员变量和方法
③ 子类可以在继承父类的基础之上,再提供自己特别的属性或方法;
子类实例化的全过程:
① 子类在继承父类以后,就获取了所的父类中声明的属性和方法;
② 实例化子类对象的过程中,间接或者直接的调用父类的构造器,或者父类的父类的构造器。因为加载了这些父类的结构,我们在子类对象的内存中调用父类声明的属性和方法;
③ 在子类对象整个实例化过程中,只创建了唯一的一个对象,即为当前的子类对象;不能创建父类对象
多态性
多态性
多态的定义:
一个事物的多种形态;
多态的体现:
广义上多态体现:
① 方法的重载和方法的重写;
② 子类对象的多态性;
狭义上多态体现:
子类对象的多态性:父类的引用指向子类的对象;
可以直接应用在抽象类和接口上
对象的多态:
在Java中,子类对象可以代替父类的对象使用
一个变量只能有一种确定的数据类型
一个引用类型变量可能指向(引用)多种不同类型的对象
应用场景:
编译时,看的是父类的引用,父类中不具备子类特有的方法;当运行时,看的是子类的对象,实际执行的是子类重写父类的方法;注意:多态中方法的调用:编译看左边,运行看右边;
当编译时和运行时类型不一样,出现了对象的多态性
方法声明的形参类型为父类类型,可以使用子类对象作为实参调用该方法
多态性的使用前提:
① 类的继承关系;
② 方法的重写;
虚拟方法调用(多态情况下)
子类中定义了与父类同名同参数方法,多态情况下此时的父类方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期时无法确定的。
向上/向下转型:
向上转型:
向上转型为多态;
向下转型:
向下转型原因:
① 由于子类的对象赋给了父类的引用,所以在编译时,只能调用父类声明的结构:属性和方法。
② 在内存结构中存在子类特有的属性和方法,我们考虑向下转型才能调用父类特有的属性和方法;
向下转型要求:
① 向下转型使用强制转化符:();
② 为了避免强转出现 Class Cast Exception 的异常,在强转前,使用 instance of 判断;
③ a instance of A : 判断对象 a 是否是类 A 的实例。如果 a 是类 A 的实例,返回 true。否则,返回 false;
注意问题:
① 使用强制类型转换符,可能出现 Class Cast Exception 的异常;
② 要求 x 所属的类与类 A 必须是子类和父类的关系,否则编译错误;
包装类:
包装类出现原因:
为了让基本数据类型的变量具有类中对象的特征;
类型间转化:
① 基本数据类型---->对应的包装类:自动装箱;
包装类---->对应的基本数据类型:自动拆箱;
② 基本数据类型、包装类---->String 类:调用 String 的重载的方法:value Of( xxx x ); 123 + "";
③ String类--->基本数据类型、包装类:调用包装类Xxx的parseXxx();
应用场景:
vector.addElement(Object obj);//int--->Integer-->Object;
推广:
很多方法的形参都是声明为类的类型。那么只能将本类或本类的子类的对象作为实参传入。那么就限制了传入基本数据类型的变量。为了能操作基本数据类型,我们需要对基本数据类型进行封装,封装为对应的包装类的对象,进而就满足形参中对类的要求;
基本数据类型与对应包装类:
基本数据类型 包装类
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double
其他关键词
abstract
语义:
abstract 抽象的;
修饰类:
格式:
class abstract 类名{类中结构}
要求:
① 不可实例化;
② 仍然存在构造器。构造器的作用:便于子类对象实例化时进行调用;
③ 通常情况,我们会提供抽象类的子类,让子类实例化,调用父类的结构;
④ 抽象类中不一定有抽象方法;抽象方法所在的类,一定是抽象类;
修饰方法:
格式:
权限修饰符 abstract 返回值类型 方法名(形参);
要求:
① 抽象方法没有方法体,所有此方法一定不能被调用;
② 如果子类重写了父类中的所的抽象方法,则此子类可以实例化;
③ 如果子类没重写父类中的所的抽象方法,则子类仍为抽象类;
注意:
① 前提:抽象性使用的前提是类的继承性;
② abstract关键字不能用来修饰:属性、构造器;
③ abstract关键字不能与 final , private , static 共用;
抽象类应用:
超类声明一个方法但不提供实现,该方法实现由子类提供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。
extends
语义:
exteds 继承(延展 扩展);
使用场景:
① 类与类的继承之间使用的继承关键词;
② 实体类与实体类之间使用的继承关键字;
③ 实体类与抽象类之间使用的继承关键字;
④ 接口与实体类之间使用的继承关键字;
⑤ 接口与接口之间使用的继承关键字;
格式:
class A extends B;
interface
语义:
interface 接口
抽象方法和常量值定义的集合
接口的使用说明:
① 接口(interface) 是与类(class)并列的结构;
② 如何定义一个接口,使用 interface 关键字;
③ 接口中只能定义常量和抽象方法 ----> JDK7.0及以前。 (JDK8.0接口中引入默认方法、静态方法);
常量:public static final 修饰;
抽象方法:public abstract 修饰;
④ 接口中不能声明构造器! 接口是不可以直接实例化的;
⑤ 类与接口之间的关系:实现(implements)关系. 类实现接口以后,就获取了接口中声明的结构:常量、抽象方法;
格式:class SubClass extends SuperClass implements Interface A;
⑥接口采用多继承机制
接口主要用途是被实现类实现(面向接口编程)
接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲,接口是一种特殊的抽象类,这种抽象类只包含常量和方法的定义(JDK7.0及之前),没有变量和方法的实现。
java8 中接口的新规定:
① 接口中可以定义静态方法、默认方法;
② 接口中定义的静态方法,只能通过接口进行调用;
③ 通过实现类的对象,调用接口中的默认方法;
④ 如果类实现的接口和继承的父类中,定义了同名同参数的方法,那么子类在没重写此方法的情况下,默认调用的是父类中声明的方法。---“类优先”原则;
⑤ 如果实现类实现了多个接口,接口中定义了同名同参数的方法。那么此时对于实现类来讲,会出现接口冲突问题;
⑥ 如何在实现类的方法中调用接口中的默认方法;
CompareA.super.method2();
⑦ (1)类实现接口以后,要么实现接口中的所抽象方法,方可实例化;
(2)要么当前类声明为抽象类(因为内部包含从接口中获取的抽象方法;
⑧ 类可以继承多个接口,接口也可以继承接口,一定程度上解决了类的单继承性;接口与接口之间可以多继承也可以单继承;
⑨ 接口与具体的实现类之间存在多态性;实际上,接口定义了一套相应功能的规范与标准。
接口的应用
代理模式(Proxy)
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
安全代理
远程代理
延迟加载
静态代理(静态定义代理类)
动态代理(动态生成代理类)
接口中默认方法
若一个接口定义了一个默认方法,另一个接口也定义了同名同参数方法,在实现类同时实现两个接口时会出现接口冲突
实现类必须覆盖接口中同名同参数方法解决冲突
若一个接口定义了一个默认方法,而父类也定义了同名同参数非抽象方法,则不会出现冲突问题
类优先原则:接口中具有相同名称和参数的默认方法会被忽略
implements
语义:
implements 实现;
使用场景:
① 实体类与接口之间的实现;
② 抽象类与接口之间的实现;
格式:
class SubClass extends SuperClass implements InterfaceA
this
定义:
当前对象 或 当前正在创建的对象;
this调用结构:
this调用属性/方法:
① 在方法中:我们可以在方法中通过"this.属性"或者"this.方法"的方法,表示调用当前对象的指定属性或方法。但是通常情况下,我们都省略了"this."。但是如果方法的形参和当前对象的属性名相同的情况下,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参;
② 在构造器中:我们可以在构造器中通过"this.属性"或者"this.方法"的方法,表示调用当前正在创建的对象的指定属性或方法。但是通常情况下,我们都省略了"this."。但是如果构造器的形参和当前正在创建的对象的属性名相同的情况下,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参;
this调用构造器:
① 可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器!
② 构造器中不能通过"this(形参列表)"的方式调用自身构造器;
③ 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(形参列表)";
④ "this(形参列表)"必须声明在类的构造器的首行!
⑤ 在类的一个构造器中,最多只能声明一个"this(形参列表)";
super
定义:
父类的对象
super调用结构:
super调用属性/方法:
① 有了继承以后,我们可以在子类的方法或构造器中,通过"super.属性"或者"super.方法"的方式,显式的调用;父类中声明的属性或方法。但是很多情况下,我们都可以省略"super.";
② 如果子类和父类中出现了同名的属性,那么我们如果在子类中调用父类中同名的属性的话,必须使用"super."的方式;说明:子类的属性不会覆盖父类中同名属性。在堆空间中,两个属性都会存在;
③ 如果子类重写了父类中的方法,那么我们我们希望在子类中调用父类中被重写的方法,必须使用"super."的方式;
super调用构造器:
① 在子类的构造器的首行,显示的使用“super(形参列表)”的方式,调用父类指定的构造器;
② 针对于子类的某一个构造器而言,只能最多声明一个“super(形参列表)”;
③ 在子类的构造器的首行,要么使用“this(形参列表)” ,要么使用"super(形参列表)",二选一,不能同时出现;
④ 子类构造器所有构造器,默认调用父类中空参数构造器
⑤ 在子类的多个构造器中,至少一个构造器的首行使用了"super(形参列表)";如果子类构造器即未显式调用父类或本类构造器,且父类中又没有无参构造器,则编译出错
static
定义:
静态的,修饰属性,方法,代码块,内部类;
static修饰结构:
static修饰属性:
① 使用static修饰的变量,被类的所对象所共享:类的所对象共同同一个静态变量;
②不用static修饰的属性,称为:实例变量。每个对象拥一份实例变量。通过对象a修改某个实例变量,不会影响其他对象同名的实例变量的值;
③ 我们可以通过对象a去调用或修改静态变量的值,那么会影响其他对象对此静态变量的调用;
内存分配:
实例变量:随着对象的创建而产生,分配在堆空间中;
静态变量:随着类的加载而产生的,分配在方法区;
static修饰方法:
① 静态方法内:可以调用静态的属性或静态的方法。不可以调用非静态的属性和非静态的方法;
② 非静态的方法内:可以调用非静态的属性和非静态的方法。也可以调用静态的属性或静态的方法;
static 使用环境:
如何判定属性是否需要声明为static的?
① 是否需要类的多个对象来共享此属性;
② 很多常量都声明为static的;
如何判定方法是否需要声明为static的?
① 操作静态变量的方法;
② 工具类中的方法。(Math.random(););
final
定义:
最终的,可以用来修饰变量、方法、类;
具体体现:
① final修饰类:此类不可以被继承。比如:String / StringBuffer类;
② final修饰方法:此方法不能被重写。比如:Object类的getClass();
③ final修饰变量:表明此变量就是一个常量。比如:Math类中的PI;
(1) 使用final修饰属性,可以考虑的赋值的位置:①显式初始化 ②代码块中初始化 ③构造器中;
(2)使用final修饰形参:在方法调用时,传递实参,给常量赋值。一旦赋值,方法内不可修改此常量的值;
instance of
作用:
判断关键字左边对象是否是关键字右边类/接口的对象/实现类的对象,如果是返回true,如果不是返回false;在向下转型时,为了避免ClassCastException,利用instance of关键字进行判断;
使用场景:
多态中的向下转型:
① 向下转型使用强制转化符:();
② 为了避免强转出现 Class Cast Exception 的异常,在强转前,使用 instance of 判断;
③ a instance of A : 判断对象 a 是否是类 A 的实例。如果 a 是类 A 的实例,返回 true。否则,返回 false;
接口和抽象类对比
main
Java虚拟机调用类的main()方法访问权限必须是public,Java虚拟机在执行main()方法时不必创建对象,该方法必须是static
main()是静态,不能直接访问类中非静态成员,必须创建类的实例对象后,才能通过这个对象访问类中成员
0 条评论
下一页