Java面向对象
1. 封装
java有三大特性:封装 继承 多态
封装也是java面向对象开发的一种思想
封装把⼀个对象的属性私有化,同时提供⼀些可以被外界访问该属性的方法
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
类的封装 ,包的封装,方法的封装 ,属性的封装 等
之前写属性,属性前面啥也没有。只要通过对象.属性就可以进行赋值和取值了,这样存在一定的隐患
对属性进行封装:
1.使用关键字 private 修饰属性2.在类中写set和get方法进行赋值和取值
2. this 关键字
字面意思:这个
只能写在声明类中,表示当前类对象
可以使用this调用当前的属性和方法
this 可以调用当前的构造方法(很少用)
只能在构造方法中去写this()。一个构造方法区调用另外一个构造方法
只能写在首行
为什么在普通方法中不能使用this()调用无参构造发
原因是:构造方法比普通方法先执行。构造方法在new对象的时候就已经执行了。方法是必须使用对象调用的
3. 匿名对象【了解】
- Person person = new Person(); 创建对象的
new Person(); 匿名对象
- 语法格式:
new 类名(); 没有等号左边的东西
- 一次性的,用完就销毁
4. 继承
java中的继承至少需要两个类,一个类是父类,一个类是子类
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码
语法格式:
class B extends A {
}
B继承了A继承的扩展,语法要求
成员属性:
- 子类是可以使用父类的公开的和默认的成员属性
- 子类是不可以使用父类私有的成员属性
成员方法:
- 子类是可以使用父类的公开的和默认的成员方法
- 子类是不可以使用父类私有的成员方法
- 总结:子类不可以使用父类下面的私有的成员变量和成员方法
- 构造方法
- 先执行父类的无参构造,然后再执行子类的无参构造
- 关于继承的两个小知识点:
B继承了A。B是A的子类。A是B的父类,超类,基类
JAVA中的继承是单继承。子类只能继承一个类。不能同时有多个父
- 什么是多重继承什么是多重继承和单继承
- 多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类
- 面向对象程序设计中的继承,可使得程序结构更加清晰,降低了编码和维护的工作量。如果一个类只能有一个父类,则这种继承关系成为单重继承;如果一个类可以有多个父类,则这种继承关系称为多重继承
5. 重写【override】
什么是方法的重写(override 或 overwrite)?
发生在运行期,子类继承父类以后,可以对父类中允许访问的同名同参数的方法,进行覆盖操作.
应用:
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
重写的规则:
权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{ 方法体 }
- 约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
- ① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
- ② 子类重写的方法的权限修饰符**>=**父类被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为private/final/static的方法,但是被static修饰的方法可以被再次声明- ③ 返回值类型:
父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)- ④ 子类重写的方法抛出的异常类型**<=**父类被重写的方法抛出的异常类型
- 子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写,要么都声明为static的(不是重写)。
- ⽅法的重写要遵循“两同两⼩⼀⼤”
“两同”即⽅法名相同、形参列表相同;
①“两⼩”指的是⼦类⽅法返回值类型应⽐⽗类⽅法返回值类型更⼩或相等 ②⼦类⽅法声明抛出 的异常类应⽐⽗类⽅法声明抛出的异常类更⼩或相等;
“⼀⼤”指的是⼦类⽅法的访问权限应⽐⽗类⽅法的访问权限更⼤或相等- 如果⽅法的返回类型是void或基本数据类型,则返回值重写时不可修改。但是如果⽅法的返回值是引⽤数据类型, 重写时是可以返回该引⽤类型的子类的。
6. super 关键字
super 关键字可以理解为:父类的
可以用来调用的结构:属性、方法、构造器
super调用属性、方法:
我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
super调用构造器:
我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
"super(形参列表)"的使用,必须声明在子类构造器的首行!
我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二一,不能同时出现
在构造器的首行,没显式的声明"this(形参列表)“或"super(形参列表)”,则默认调用的是父类中空参的构造器:super()
在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
7. 重载【overload】
- 方法的重载的概念
- 定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
总结:“两同一不同”:同一个类、相同方法名
参数列表不同:参数个数不同,参数类型不同如何判断是否构成方法的重载?
严格按照定义判断:两同一不同。跟方法的权限修饰符、返回值类型、形参变量名、方法体都没关系!
重载就是同⼀个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
【总结】:
1.方法的重载必须写在一个类中
2.方法名字是一模一样的
3.方法的参数一定不一样
4.方法的返回值可以一样也可以不
5.构造方法,无参构造方法和有参构造方法也是方法重载的
7.1面试题:
区分方法的重写和重载?
答:
① 二者的概念:
② 重载和重写的具体规则
③ 重载:不表现为多态性。 重写:表现为多态性。
- 重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数列表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。所以,对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;而对于多态,只等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”
8. 抽象类【重点】
在面向对象概念中,所有的对象都是通过类来描绘的。通过类来创建对象。但是反过来说,并不是所有的类都可以用来描绘对象的。如果一个类中没有足够的信息来描绘具体的对象的话,这个类叫抽象类。
在java中 使用关键字 abstract修饰的类叫抽象类。
9. abstract 关键字
abstract修饰的方法叫抽象方法
abstract修饰的类叫抽象类
【注意事项】
1. 如果一个类中有抽象方法,那么这个类必须是抽象,不然语法会报错
2.使用abstract修饰的方法,没有方法体,是一个不完整的方法。小括号后面分号结束
3.抽象类能被实例化吗? 不能
4.抽象类下面可以有非抽象方法吗? 可以有正常方法!!!
5.由于抽象类不能被实例化,可以使用一个普通的类去继承它然后使用
6.普通类去继承抽象类的时候,一定要重写抽象类下面的抽象方法,让抽象方法变得有意义
7.在抽象类中的普通方法,可以重写也可以不重写。看需求了。
8.牵涉到继承,只能是单继承。
9.抽象类能不能继承另外一个抽象类? 能
10. final关键字
- 字面意思:最后的最终的
- 用法:
- final可以修饰成员变量,使用final修饰非成员变量必须进行赋值(初始化)。一旦赋值以后这个值不能改变。
- final修饰局部变量的时候可以先不赋值,然后再赋值,但是赋值以后不能被修饰改
- final修饰成员方法不能被重写
- final修饰的类不能被继承!!!
11. 接口【重点】
- 语法格式:
interface 接口名字 { 成员属性 成员方法 }
- 【注意事项】
- 接口下面可以声明成员属性,但是必须进行赋值。在接口中变量默认的修饰符是final和static【很少用】
- 接口下面的方法都是默认的抽象方法
- 接口中年的方法可以带方法体,但是使用default修饰
- 接口中没有构造方法,可以通过匿名内部类进行实例化
- 一个类可以实现多个接口,相当于多继承
- 一个接口能继承另外一个接口
- 总结:类和接口使用implements 接口和接口使用继承extends
12. 多态
12.1 Java中的多态
Java中的多态是指同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
Java中的多态其实是一种运行期的状态。为了实现运行期的多态,或者说动态绑定,需要满足三个条件:
- 有类继承或者接口实现
- 子类要重写父类的方法
- 父类的引用指向子类的对象
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但是在运行期,我们实际指向的是子类重写父类的方法。即编译,看左边;运行,看右边;
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
12.2 关于向上转型和向下转型
- 向上转型指的是Java中的多态
- 向下转型:
- 为什么要使用向下转型
- 有了对象的多态性以后,内存中实际是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。此时,就要使用向下转型来调用子类特有的方法和属性。
- 如何实现向下转型
- 使用强制类型转换符:()
- 使用时的注意点:
- 使用强转时,可能出现ClassCastException的异常。
- 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进性instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
- 总结:要先向上转型,才能向下转型。
- instanceof的使用:
- a instanceof A:判断对象a是否是类A的实例。如果是,返回itrue;如果不是,返回false
- a instanceof A 返回true,则a instanceof B 也会返回true,其中类B是类A的父类
13. static 关键字
static:静态的
- 可以用来修饰的结构主要是类的内部结构:属性、方法、代码块、内部类
- static修饰属性:静态变量
- 属性,是否使用static修饰,又分为:静态属性、非静态属性(实例变量)
- 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量是,会导致其它对象调用此静态变量是,是修改过的。
- 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象的非静态属性时,不会导致其他对象中同样的属性值的修改。
- 静态变量的内存分析
- static 修饰方法:静态方法、类方法
- 随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
区别 | 静态方法 | 非静态方法 |
---|---|---|
类 | yes | no |
对象 | yes | yes |
- static 的注意点:
- 在静态的方法内,不能使用this关键字、super关键字
- static 修饰代码块
- 语法格式:static { 代码 }
- 只要类文件加载,静态代码块就会被加载
- 静态代码块的执行早于构造代码块和构造器,因为构造代码块和构造器是在对象创建以后才有的