本质
面向对象编程(Object-Oriented Programming,OOP),本质就是以类的方式组织代码,以对象的组织(封装)数据。
面向过程是具体的、面向对象是抽象的。
抽象
三大特性: 封装、继承、多态
类和对象的关系
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
例: 动物、植物、手机…
Person类、Pet类、Cat类,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。
对象是抽象概念的具体实例。
例:李四就是人的一个具体实例,李四的狗狗jack就是Cat的一个具体实例
能够体现出特点,展现出功能的是具体的实例,而不是抽象的概念
创建与初始化对象
使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能有void
构造器
- 使用new关键字,本质是调用构造器,必须使用构造器
- 用来初始化值
一旦定义了有参构造,如果想使用无参构造,必须显示定义无参构造。
封装
- 该露的露,该藏的藏
设计程序追求“高内聚、低耦合”。高内聚指的是类的内部数据操作细节自己完成,不允许外部干涉;低耦合指的是尽暴露少量的方法给外部使用。
-
封装(数据的隐藏)
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这成为信息隐藏。
属性私有(private),get/set
继承
本质是对某一批类的抽象,从而实现对现实世界的更好建模。
extends的意思是“扩展”,子类是父类的扩展。
注意:Java只有单继承,没有多继承。(一个儿子只能有一个爸爸,一个爸爸可以有多个儿子)
继承是类于类之间的一种关系。除此之外,类与类之间的关系还有依赖、组合和聚合
继承关系是两个类。一个父类(基类),一个子类(派生类),子类继承父类使用extends来表示
子类和父类之间,从意义上讲应该是“is a“ 的关系
私有的父类属性不能继承。(可以通过get/set来实现继承)
子类调用父类使用super
public class Stu extends Person{
private String name = "Halo";
public void test(String name){
//这里的name是调用的test的形参name
System.out.println(name);
//这里的name调用的Stu类中的私有属性name
System.out.println(this.name);
//这里的name调用的是父类的name属性
System.out.println(super.name);
}
}
执行过程:子类的无参构造中有隐藏的super,所以调用父类的构造器,必须要在子类构造器的第一行。
super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时出现在构造方法中
super和this的区别
代表的对象不同:
- this:本身调用者这个对象
- super:代表父类对象的应用
前提:
- this:没有继承也可以用
- super:只能在继承条件下才可以使用
构造方法:
- this(); 本类的构造
- super(); 父类的构造
方法的重写
重写都是方法的重写,和属性无关!@Override
静态方法和非静态方法区别非常大!
静态方法:方法调用只和左边定义的数据类型有关。
重写之和非静态有关系!
因为静态方法
class A extends B{
public static void test(){
system.out.println("A->test");
}
}
class B{
public static void test(){
system.out.println("B->test");
}
}
public static void main(String[] args){
A a = new A();
a.test(); //输出A->test
B b = new A();
b.test(); //输出B->test
}
class A extends B{
@Override
public void test(){
system.out.println("A->test");
}
}
class B{
public void test(){
system.out.println("B->test");
}
}
public static void main(String[] args){
A a = new A();
a.test(); //输出A->test
B b = new A();
b.test(); //输出A->test
}
重写:需要有继承的关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小: public-> protected -> default ->private
- 抛出的异常:范围可以缩小,但不能扩大:ClassNotFoundException -> Exception
重写:子类的方法和弗雷德必须一致,方法体不同!
Why需要重写?
A:父类的功能,子类不一定需要或者不一定满足!
多态
即同一个方法,可以根据发送对象的不同而采用不同的行为方式。
一个对象的实际类型是确定的,但是可以指向对象的引用的类型有很多。
- 多态是方法的多态,属性没有多态!
- 父类和子类有联系, 没有关系的会报出类型转换异常!ClassCastException
- 存在的条件:
- 继承关系
- 子类重写父类的方法,以下方法不会被重写:
- static 方法属于类,不属于实例
- final 常量
- private 方法
- 父类的引用指向子类 Father F = new Son();
static关键字
public class Person{
{
System.out.println("匿名代码块");
}
static{
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args){
Person person = new Person();
}
}
执行结果:
静态代码块
匿名代码快
构造方法
public class Person{
//赋初始值
{
System.out.println("匿名代码块");
}
//只执行一次
static{
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args){
Person person1 = new Person();
System.out.println("=============");
Person person2 = new Person();
}
}
执行结果:
静态代码块
匿名代码快
构造方法
==========
匿名代码块
构造方法
静态导入包
当只导入包中指定的方法,可以使用static关键字。例:
import static java.lang.Math.random;
public class Test{
public static void main(String[] args){
System.out.println(random());
}
}
和下面的方式一样
import static java.lang.Math;
public class Test{
public static void main(String[] args){
System.out.println(Math.random());
}
}
抽象类
是一种约束,有人能帮你实现。abstract,抽象方法,只有方法的名字,没有方法的实现!
- 不能new这个抽象类,只能靠子类去实现它;约束!
- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
接口
普通类:只能有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只是规范,自己无法写方法~专业的抽象!约束和实现的分离:面向接口的编程(即可以实现多继承)
声明类的关键字是class,声明接口的关键字是interface
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是猫,就必须会捉老鼠。
接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
oo的精髓是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式都是只针对具备了抽象能力的语言(比如c++,java,C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
作用
- 约束
- 定义一些方法,让不同的人实现
- 方法默认都是public abstract
- 常量默认都是public static final
- 接口不能实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须重写接口中的方法
内部类
内部类就是在一个类的内部定义一个类,比如,A类中定义一个B类,那么B类相对于A类来说就是称为内部类,而A类相对B类磊说就是外部类。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类
通过这个外部类来实例化内部类
public class Outer{
public class Inner{
public void in(){
System.out.println("这是内部类方法");
}
}
}
public class Test{
public static void mian(String[] args){
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
获取外部内的私有属性
public class Outer{
private int age=10;
public class Inner{
public void in(){
System.out.println("这是内部类方法");
}
public void getAge(){
System.out.println(age);
}
}
}
局部内部类
public class Outer{
public void method(){
//在方法中在构建类
class Inner{
}
}
}
异常机制
五个关键字:
try
catch
finally
throw
throws
throw 是语句抛出一个异常;throws 是方法抛出一个异常;
- throw语法:throw <异常对象>
在方法声明中,添加throws子句表示该方法将抛出异常。 - throws语法:[<修饰符>]<返回值类型><方法名>([<参数列表>])[throws<异常类>]
【其中:异常类可以声明多个,用逗号分割。】
- 处理运行时异常,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句去释放占用的资源