面向对象编程

本文详细介绍了面向对象编程的核心概念,包括类与对象的创建、访问字段和方法,以及this关键字的使用。深入讲解了内存分析中的对象创建过程,展示了如何定义和调用方法,包括形参和实参的区别。此外,还阐述了方法的重载、可变长参数、参数传递机制、封装、构造方法、继承、super关键字的运用、方法重写(override)以及多态的概念。通过对示例代码的解析,帮助读者理解这些概念的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象编程

类和对象

类的创建

语法

[修饰符]    class 类名{类体:包含各种成员}
类名采用驼峰命名法 
  • 类对象的创建
 类名 变量名=new 类名();
  • 访问对象中的字段和方法
对象.字段
对象.方法
this关键字
  • this关键字 可以理解成 我 , 本身的含义 指代 当前对象 。
  • this关键字可用来引用当前类的 实例变量 。 谁调用就是谁
  • this关键字可用于调用 当前类中实例方法(隐式)。 在实例方法中,可以直接调用 其他的实例方法,而不用书写this关键字 , 会自动加上, 但是建议书写!
  • this()可以用来调用当前类的 构造函数。
  • this关键字可作为调用实例方法中的 参数传递。 调用实例方法的时候,可以将 this 作为参数进行传递, 此时的this 依旧是 当前对象。
  • this关键字可作为参数在构造函数调用中传递。 此时 this 依旧是一个 当前对象
  • this关键字可用于从方法返回当前类的实例。 在方法中 , 使用 this 作为一个返回 。返回当前对象,谁调用就返回谁!
内存分析之创建对象

示例

public class Person {
    int age;
    String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public static void main(String[] args) {
        Person p=new Person(12,"张三丰");
    }
}

在这里插入图片描述

当执行 Person p=new Person ; 的时候,首先会在 栈(stack) 中 声明 Person类型的变量 p , 然后在堆(heap)中开辟空间【是new 的作用】 ,会为 Person 类中的字段(Field)设置默认值(前提是没有进行指定值) 并 执行Person() 中的代码(构造器中的代码),最后通过 = 将 堆中的地址 复制给p 变量。
static 修饰的内容会被放在方法区(Method area)中

方法

语法

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}

示例

public class MethodUse {
    public void method(){
        System.out.println("这就是方法的定义!!!");
    }

    public static void main(String[] args) {
        MethodUse methodUse=new MethodUse();
        methodUse.method();
    }
}

注意:方法内部不能再定义方法,但是可以调用方法。如果没有返回值,则要写上void。返回值类型可以是基本数据类型,也可以是引用数据类型。

形参和实参
  • 形参:形式参数,在方法声明时,()中的参数。
  • 实参:实际参数,在方法调用时直接传入的参数。
方法的属主

static修饰的方法应该用类名来调用。
非static修饰的方法(实例方法)应该用对象来调用。
示例

public class MethodOwner {
    int age;
    String name;

    public MethodOwner(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void show(){
        System.out.println(this.name+this.age);
    }
    public static void sleep(){
        System.out.println("开始睡觉了!!!");
    }

    public static void main(String[] args) {
        MethodOwner methodOwner=new MethodOwner(12,"张三丰");
        methodOwner.show();
        //static修饰的方法只能通过类名来调用
        //methodOwner.sleep();
        MethodOwner.sleep();
    }
}
方法重载

同一个类中有两个或两个以上方法同名不同参的方法,称为方法重载(满足同名不同参)
特点:

  • 同一个类 , 如果存在继承,那么需要保证 继承来的方法 与 本类中自己的方法 同名不同参
  • 同名 : 方法名相同
  • 不同参 : 参数 个数、顺序、类型 不一样
  • 返回值 与 修饰符 不做要求 。
    示例
//父类
public class OverLoad {

    public void add(String a,int b){
        System.out.println(a+b);
    }
}

//子类
public class OverLoadInherit extends OverLoad{
    //参数类型不同
    public double add(double a, double b) {
        return a+b;
    }
    //参数个数不同
    public int add(int a){
        return a;
    }
    //参数顺序不同
    public void add(int a,String b){
        System.out.println(a+b);
    }
}
可变长参数

参数在 方法调用的时候出现 ; 而参数的个数,相同类型可以有多个 , 但是 可以不用在 方法调用时 传递那么多的参数。
语法

数据类型...形参名字

示例

public void foo(String...args)

注意:

  • 可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数
  • 由于可变参数必须是最后一个参数,所以一个函数最多只能有一个可变参数
  • Java的可变参数,会被编译器转型为一个数组
  • 变长参数在编译为字节码后,在方法签名中就是以数组形态出现的。这两个方法的签名是一致的,不能作为方法的重载。如果同时出现,是不能编译通过的。可变参数可以兼容数组,反之则不成立
    示例
public class VariableArgs {
    String name;
    public void show(String...names){
        for(String name:names){
            System.out.println(name);
        }
    }
    public static void main(String[] args) {
        VariableArgs variableArgs=new VariableArgs();
        variableArgs.show("张三丰","张无忌","令狐冲");
        //直接传递数组也行
        variableArgs.show(new String[]{"张三丰","张无忌","令狐冲"});
    }
}
参数传递机制

在Java 中, 只存在一种 参数传递机制 : 值传递。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。

  • 基本数据类型 : 将实参基本数据类型变量的“数据值”传递给形参
  • 引用数据类型 : 将实参 引用数据类型变量 的 ”地址值“ 传递给形参

封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
通过 权限修饰符 可以将 一些内容 藏起来 . 注意:权限修饰符一共有 3个, 但是 访问级别有 4 个 .

  • 权限修饰符 : private ( 私有的 ) , protected( 受保护的 ) , public( 公开的 )
  • 访问级别 : private , 缺省的( 来自于C++ , C++ 中关键字为default , 在Java 中不存在对应的关键字) 或 默认的, protected , public
    访问级别表:
    img

封装的实现
示例

public class Person {
    private int age;
    String name;
    protected String sno;
    public double weight;

    //使用public方法来对私有自动进行获取
    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}


public class TestPerson {
    public static void main(String[] args) {
        Person p=new Person();
        //私有字段只能在其类中访问
        //p.age=12;
        p.name="张三丰";
        p.sno="1212";
        p.weight=213123;
        //通过共有方法访问私有字段
        p.setAge(12);
        p.getAge();
    }
}
  • 构造
    构造 又称 构造方法、构造器 (Constructor) 、构造函数 。是一个类里用于创建对象的特殊子程序 。
    构造就是为了 构建一个对象 而存在 。 并且 经常接收一些参数,用来为 实例变量(非static 修饰的 字段 ) 赋值 。
    语法
【修饰符】 类名( 【形参】 ){ 方法体 ;}

如果一个构造方法 没有任何参数,此时可以被称为 无参构造 。
构造方法与普通方法之间的区别

  • 构造方法没有任何返回值 , 也就是说没有返回类型; 普通方法存在 返回类型
  • 构造方法的名称 是 类名 , 如果不是类名就会变成一个普通的方法; 普通方法的方法名 是可以随便书写。
    构造之间的重载
  • 所有的构造方法的名字都是 类名 。 —— 同名
  • 构造方法中的 参数的 个数、类型、顺序 不同 。—— 不同参
  • 对修饰符没有任何要求 。
    默认构造 : 当创建一个类的时候, 如果没有明确书写构造方法,则 JDK 会自动加上一个 public 修饰 无参构造 。但是,如果一旦书写了任何一种构造方法,那么JDK 就不会再次提供 构造方法了。所以, 在添加构造方法的时候,一般 需要提供一个 public 修饰的无参构造。
    构造方法本身没有任何返回 , 但是 new + 构造方法 有返回值 .

示例

public class Animal {
    private String name;
    private int age;
    public Animal(){
        System.out.println("无参构造执行了!!!");
    }
    public Animal(String name){
        this(name,12);
        System.out.println("有参构造执行了!!!");
    }
    //构造方法重载
    public Animal (String name,int age){
        this.name=name;
        this.age=age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    public static void main(String[] args) {
        Animal animal1=new Animal();
        Animal animal=new Animal("Dog");
    }
}

继承

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
子类可以继承父类所有的字段和方法,但是能不能访问由访问权限来决定。
java.lang.object是所有类的父类。java只能单继承。
示例

//父类
public class Animal {
    private String name;
    private double weight;

    public Animal() {
    }

    public Animal(String name, double weight) {
        this.name = name;
        this.weight = weight;
    }

    public void eat(){
        System.out.println("我的名字是:"+this.name+",我要吃饭了");
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}

//子类
public class Dog extends Animal{

    //子类可以新增内容
    public void sleep(){
        System.out.println("开始睡觉!!!");
    }
}

//主函数测试
public class Test {
    public static void main(String[] args) {

        Dog dog=new Dog();
        dog.setName("poppy");
        dog.setWeight(20);
        String name = dog.getName();
        System.out.println(name);

        dog.eat();
        dog.sleep();
    }
}
super 关键字

this 表示我, super 表示 我父亲
super关键字是一个引用变量,用于引用直接父类对象 . super 关键字 可以代表 父类的一些东西 .
用法 :

  • 可以表示父类的 实例对象 . 表示父对象 . 注意:有可能是 直接父级对象 或 间接父级对象 .
  • super() ; 表示调用父类的构造方法 . 在 子类中的构造中使用 , 是放在 子类构造中的第一行! 如果没有书写,则JDK 会 隐式(偷偷摸摸的) 添加这一行
    示例
//父类
public class Animal { 
    private String name;  
    private int id; 
    public Animal(String myName, int myid) { 
        name = myName; 
        id = myid;
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "号" + name + "."); 
    } 
}

//子类
public class Mouse extends Animal { 
    public Mouse(String myName, int myid) { 
        super(myName, myid); 
    } 
}
重写(override)

重写( override )与重载( overload )的异同
重写 : 同名( 方法名相同 ) 同参( 参数相同 ) 同返回( 返回类型相同 )

  • 发生在 继承 关系中
  • 方法名相同 , 参数 相同 ( 参数的个数 类型 顺序 )
  • 返回类型 :
    • 基本数据类型 : 完全一致
    • 引用数据类型 : 保证 “同源”
  • 修饰符 : 子类重写方法的修饰符 不能 比 父类方法中的修饰符 要小 ( 访问权限 )
    示例
//父类
class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}

//子类
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
}
 
//主函数测试
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
      a.move();// 执行 Animal 类的方法
      b.move();//执行 Dog 类的方法
   }
}

多态

多态是 同一个行为 具有多个 不同表现形式或形态 的能力。

分类
  • 运行时多态 : 发生的基础 是继承 . 同时 保证 子类重写了 父类 的 方法. 本质是 父类类型指向子类对象 ( 父类变量指向了 子类对象 )
  • 编译时多态 : 是由 重载 决定的. 在 .java 文件 编译阶段 表现出 多种形态 . 实际上 是由 参数的多样化 决定的.
    运行时类型与编译时类型 :
  • 运行时类型 : Human h = new Chinese() ; 在 运行阶段, 引用的 是 Chinese 类型, 那么 运行时类型就是 Chinese . Human h = new Hindu() ; 在运行阶段 , 引用的是 Hindu 类型, 那么对应的运行时类型就是 Hindu.
  • 编译时类型 : Human h = new Chinese() ; 此时的 h 的类型是 Human, 这个类型就是编译时类型 Human h = new Hindu() , 此时 h 的编译时类型时 Human .
instanceof

含义 : xxx 是 YYY 吗 ? 返回值是 boolean 类型 ; 判断变量的运行时类型
语法

变量 instanceof 类

示例
多态和instanceof结合

//父类
public class Animal {
    public void call(){
        System.out.println("动物的叫声");
    }
}

//子类
public class Dog extends Animal{
    @Override
    public void call(){
        System.out.println("狗的叫声:汪汪汪");
    }
}

public class Duck extends Animal{
    private String name ;
    @Override
    public void call(){
        System.out.println("鸭子的叫声:嘎嘎嘎");
    }
}

//主函数测试
public class TestPolymorphism {
    public static void main(String[] args) {
        show(new Dog()) ;//以Dog对象调用show方法
        show(new Duck());//以Duck对象调用show方法

        Animal animal = new Dog() ;//向上转型
        animal.call();//调用的是Dog的call方法
        Dog dog = (Dog)animal;//向下转型
        dog.call();//调用的是Dog的call方法
    }

    public static void show(Animal animal){
        animal.call();
        if (animal instanceof Dog){
            Dog dog = new Dog() ;
            dog.call();
        }else if (animal instanceof Duck){
            Duck duck = new Duck() ;
            duck.call();
        }
    }
}

引用强制类型转换的本质
Dog dog = (Dog)animal; dog并转换成目标类型(Dog)

static关键字

static 表示 静态的 , 表示 类加载 初始化阶段 , 可以修饰 变量、方法、代码块、内部类(内部接口) 。
static 修饰的内容 是通过 类名.变量(方法) 直接使用

  • 修饰变量 ( 静态变量, 静态成员变量, 类初始化变量, 类初始化字段 ) , 一般是 在 类中 直接使用, 表示 该变量 在 类 初始化的时候 就已经定义好了。
  • 修饰方法 ( 静态方法 ) , 一般是 在类中直接使用, 表示 该方法 在 类 初始化的时候 就已经定义好了。
  • 修饰代码块 : 就可以表示 类已经被加载了, 类加载阶段就会执行的代码。
变量分类
  • 变量的作用域 : 离变量最近的花括号{}。
  • 成员变量
    • static修饰 (静态成员变量 、类初始化成员变量 ) : 加载到 方法区中, 伴随着 类的存在而存在。
    • 实例变量(没有使用 static 修饰的变量 ) : 随 对象存在而存在, 加载到 堆空间 中 , 作用范围是 整个类体括号
  • 局部变量
    • 在 方法中 或 代码块中定义 ; 作用范围在声明的范围之内 ; 加载到栈中
代码块

代码块与 变量的分类是差不多的。
语法:

[修饰符] { 
此时就是一个代码块了!
}
  • 成员代码块
    • 静态代码块(类初始化代码块) 使用 static 修饰的代码块
    • 实例代码块 : 没有使用 static 进行修饰的代码块
  • 局部代码块 : 在 方法内部 直接 声明的代码块 , 很少使用。

执行顺序

  • 一个类中存在 代码块、static代码块、构造方法 的时候, 先 static 代码块, 再 代码块, 最后是构造。
  • 一个类中存在 多个 代码块 , 多个 static代码块 、 构造的时候, 先 static 代码块, 再 代码块, 最后是构造。
    • 多个代码块的时候,会按照 书写顺序(从上到下)执行
    • 当 static 代码块 执行的时候,就可以认为 这个类 已经被加载到 jvm 中了。
  • 存在继承的时候,代码块 、 static 代码块 、 构造的执行顺序
    • 父类静态代码块
    • 子类静态代码块
    • 父类实例代码块
    • 父类构造方法
    • 子类实例代码块
    • 子类构造方法
      示例
//父类
public class Animal {
    public Animal() {
        System.out.println("父类构造方法");
    }
    static {
        System.out.println("父类静态代码块");
    }
    {
        System.out.println("父类实例代码块");
    }
}

//子类
public class Dog extends Animal{
    public Dog() {
        System.out.println("子类构造");
    }
    static {
        System.out.println("子类静态代码块");
    }
    {
        System.out.println("子类实例代码块");
    }
}

//主函数测试
public class TestStatic {
    public static void main(String[] args) {
        Dog d = new Dog() ;

    }
}
final

final : 最后的, 最终的 , 不可改变的 。
final 可以修饰 变量 、 非抽象方法、 非抽象类 。

  • final 修饰的变量 不可改变
  • final 修饰的方法 不可 重写
  • final 修饰的类 不可 继承
    示例
//示例1
//final修饰的字段
public class User {
    //用户身份证号
    //final修饰的就是不可更改的量
    private final String ID ;

    public User(String ID) {
        this.ID = ID;
        //一旦重新赋值,编译失败
        //this.ID = "111111111111111111111";
    }

    public static void main(String[] args) {
        User user =new User("123");
        System.out.println(user.ID);

        User u = new User("456");
        System.out.println(u.ID);
    }
}



//示例2
//final修饰的方法
public class Animal {
    public final void call(){
        System.out.println("动物的叫声");
    }

}

public class Dog extends Animal {
    //无法重写
    //@Override
    //public final void call(){
        //System.out.println("狗的叫声:汪汪汪");
    //}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值