Java基础---面向对象

这篇博客详细介绍了Java的面向对象编程,包括封装、继承、多态等核心特性。讲解了类与对象的关系,类的创建与初始化,特别是构造器的使用。还深入探讨了内存分析、封装、继承的细节,如方法重写、子类继承和多态的概念。此外,还提到了抽象类和接口的使用,以及异常处理的基本框架和方法。
摘要由CSDN通过智能技术生成

面向对象

一、Java的三大特性

封装,继承,多态


面向对象编程的本质:以类的方式组织代码,以对象的方式组织(封装)数据

 

二、类与对象的关系

  • 类是一种抽象的数据类型,是对一类事物的整体描述/定义,类是对象的模板
  • 对象的是抽象概念的具体实例

从认识论的角度考虑是先有对象后有类,从代码运行角度考虑是先有类后有对象

一个类中只有属性和方法

 


三、类的创建与初始化

1、创建对象

使用new关键字来创建对象,除了分配内存空间,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用。

//类实例化后会返回一个自己的对象
Student student = new Student();

 

2、初始化对象(Constructor : コンストラクタ)

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点

  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void

构造器分为有参构造和无参构造,类中什么都不写的话默认有一个无参构造器,写了有参之后会覆盖默认的无参构造器,若需要使用无参,写出无参构造即可。

public class Person{
    //使用new关键字,本质是在调用构造器
    //无参构造
    public Person(){
        
    }
}

public class Student{
    int age;
    
    //有参构造
    public Student(int num){
        this.age = num;//初始化对象的值
    }
    //无参构造
    public Student(){
        //初始化对象的值
    }
}

 


四、创建对象内存分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lPW1j1JN-1645893776977)(E:\开发学习记录\附件\内存分析.png)]

实际内存很复杂,这里只分析创建对象时的内存。分为两个空间,

中有一块独特的区域叫方法区,类这个模板就存放在方法区中,除了类还有常量池,静态方法区等也都存放在方法区中。静态方法区和类是同级别的存在,和类一起加载。

new Person()的时候会在堆中开辟一块空间,这就是对象。

Person p = new Person();

需要注意的是,p不是对象,new Person()才是对象,p作为引用变量名,存放在栈中,保存的是指向对象的内存地址。

 


五、封装

程序设计追求高内聚,低耦合,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用。

封装(数据的隐藏),通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问。

使用private将类中的属性隐藏起来,让外部在调用这个类的时候无法直接访问类的属性。

属性私有,get/set

通过gettersetter来访问和修改属性。

public int getAge() {
    return age;
}
public void setAge(int age) {
    this.age = age;
}

 


六、继承

继承的本质是对某一批类的抽象

1、子类继承

使用extends来继承父类,Java中只有单继承,没有多继承。所有的类都直接或间接继承Object类。

子类继承了父类,就会拥有父类的全部方法。私有的东西无法被继承

父类和子类之间,从意义上来讲应该具有is a的关系

public class Student extends Person{
    //
    public Student{
        super();//隐藏代码,调用了父类的构造器,必须要在子类构造器的第一行
    }
}
  • super注意点
    1. super调用父类的构造方法,必须在构造方法的第一个
    2. super必须只能出现在子类的方法或者构造方法中
    3. superthis不能同时调用构造方法
  • this的不同
    1. 代表的对象不同
      • this:本身调用者这个对象
      • super:父类对象的应用
    2. 前提
      • this:没有继承也可以使用
      • super:只能在继承条件才可以使用
    3. 构造方法
      • this:本类的构造
      • super:父类的构造

 


2、方法重写

继承了父类的子类可以重写父类里面的方法。

在父类里面定义的方法无法满足子类的需求时,通过继承获得父类属性以及其他方法的同时,可以对不满足需求的方法进行重写,来实现更精细的操作。

// 假设有A、B两个类,其中A extends B
public class test{
    A a = new A();// 普通操作,类名 对象名 = 在内存中开辟一块空间
    
    // 父类的引用指向了子类,因为有父子关系所以ok
    B b = new A();// 多态操作,父类类名 对象名 = 在内存中开辟一块空间
}

方法的调用只和左边有关系(定义的数据类型),上面的b只可以调用B类中的方法,但是如果A类重写了B类中的方法,则方法体的执行按重写后的A类的方法执行。b无法调用A类中独有的方法
 

3、重写条件:需要有继承关系,子类重写父类的方法

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大,不可以缩小
    • public > Protected > Default > private
  4. 抛出的异常:范围可以缩小,不可以扩大
    • Exception > ClassNotFoundException
  5. 子类的方法必须和父类一致:方法体不同

无法被重写的方法

  1. static方法,属于类,不属于对象
  2. final常量
  3. private方法

 


七、多态

同一方法可以根据发送对象的不同而采用多种不同的行为方式

一个对象的实际类型是确定的,但可以指向对象的引用类型有很多

  • 多态存在的条件
    • 有继承关系
    • 子类重写父类的方法
    • 父类引用指向子类对象

多态是方法的多态,属性没有多态性

//一个对象的实际类型是确定的
new Student();
new Person();

//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();

类型转换

子类转换为父类,向上转型,低转高==自动转换

Student student = new Student();
Person person = student;

父类转换为子类,向下转型,高转低==强制转换

Person obj = new Student();
Student student = (Student)obj;
//or
((Student) obj).method();

子类转换为父类,可能会丢失自己的本来的一些方法

 


八、抽象类

abstract修饰符可以用来修饰方法也可以修饰类,修饰方法就是抽象方法,修饰类就是抽象类

public abstract class Action{
    //约束,其他地方实现
    //抽象方法,只有方法名字,没有方法实现
    public abstract void doSomething();
}

抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类

  • 抽象类不能使用new关键字来创建对象,是用来让子类继承的
  • 抽象方法只有方法的声明,没有方法体
  • 子类继承抽象类,就必须实现抽象类没有实现的抽象方法(重写),否则也必须声明为抽象类
  • 抽象类中可以写普通方法
  • 提高开发效率,节省代码

由于继承只能单继承,与接口相比用的相对较少

 


九、接口

普通类:只有具体实现

抽象类:既有具体实现,也有规范(抽象方法)

接口:只有规范,约束和实现分离

声明类的关键字是class,声明接口的关键字是interface

//interface 关键字,接口都需要有实现类
public interface UserService{
    //接口中的所有方法都是抽象的 public abstract
    void add(String name);
}
public interface TimeService{
    //接口中定义的属性都是常量 public static final
    int AGE = 26}

//接口可以多继承
public class UserServiceImpl implements UserServiceTimeService{
    @Override
    public void add(String name){
        //方法体
    }
}
  • 类通过implements实现接口
  • 实现了接口的类,就需要重写接口中的所有方法
  • 接口可以实现多继承
  • 接口不能被实例化,没有构造方法

 


十、异常

异常处理框架

有三种类型的异常

  • 检查性异常:用户错误或问题引起的异常,程序员难以预见
    • 例如要打开一个不存在的文件,这些异常在编译时不能被简单的忽略
  • 运行时异常:可能被程序员避免的异常,在编译时会忽略
    • 例如11/0的计算,编译时忽略,运行时抛出ArithmeticException
  • 错误Error:错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略
    • 例如当栈溢出时,一个错误就发生了,在编译时也检查不到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f5yWt7in-1645893776978)(E:\开发学习记录\附件\异常体系结构.png)]

 

捕获和抛出异常

Java实际运行中发生的所有异常都是可以被捕捉到的

异常处理五个关键字trycatchfinallythrowthrows

如果不使用trycatch,程序报错后会停止运行,使用后会继续向下执行

try{
    //try监控区域,在此区域内写的代码如果有异常即可通过catch捕获
}catch (ArithmeticException e){//参数为想要捕获的异常类型
    //捕获异常,需要知道捕获的异常的类型
    //捕获到相应异常之后执行catch内的代码
}catch (Throwable e){
    //可以捕获多个异常,范围大的写在后面
}finally{
    //无论是否发生异常,都会执行这里面的代码
    //通常用于关闭IO流或资源,处理善后工作
    //可以不写finally
}

如果预见到有可能会报错,可以主动抛出异常

if(a == 0){
    throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}

假设在方法中处理不了这个异常,可以在方法上抛出异常

public void run() throws Exception{
    //方法体
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值