Java基础回顾——面向对象编程

news2024/12/23 10:46:59

文章目录

  • 面向对象基础
    • 方法
    • 构造方法
      • 默认构造方法
      • 多构造方法
    • 方法重载
    • 继承
    • 多态
    • 抽象类
    • 接口
    • 静态字段和静态方法
    • 作用域
    • 内部类
  • 写在最后

https://www.liaoxuefeng.com/wiki/1252599548343744/1255943520012800

面向对象编程Object-Oriented Programming,简称OOP,是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法

面向对象基本概念

实例
方法
面向对象的实现方式
继承
多态
Java语言提供的机制
package
classpath
jar
Java标准库提供的核心类
字符串
包装类型
JavaBean
枚举
常用工具类

面向对象基础

面向对象编程,就是通过对象的方式,把现实世界映射到计算机模型的一种编程方法

class和instance
class是一种对象模板,定义了如何创建实例
instance是对象实例,是根据class创建的实例,可以创建多个instance,每个instance类型相同,但各自的属性可能不同

class Person{
	// field
	public String name;
	public int age;
}
Person ming=new Person();
ming.name="Xiao Ming";
ming.age=18;
Person hong=new Person();
hong.name="Xiao Hong";
hong.age=19;

在这里插入图片描述

方法

class中直接把field用public暴露给外部可能会破坏封装性

直接操作filed,容易造成逻辑混乱,未来避免外部代码直接访问field,可以用private修饰field,拒绝外部访问

class Person{
	// field
	private String name;
	private int age;
}

修改之后,外部无法访问field,想要给field赋值需要使用方法(method)来让外部代码间接修改field:

class Person{
	// field
	private String name;
	private int age;
    public String getName() {
        return this.name;
    }

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

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

    public void setAge(int age) {
        if (age < 0 || age > 100) {
            throw new IllegalArgumentException("invalid age value");
        }
        this.age = age;
    }
}

一个类通过定义方法,就可以给外部代码暴露一些操作的接口,同时,内部自己保证逻辑一致性。

private方法
private方法不允许外部调用,但内部方法可以调用

this变量
方法内部,可以使用一个隐含的变量this,始终指向当前实例。因此,通过this.field就可以访问当前实例的字段。

方法参数
方法可以包含0个或任意个参数。方法参数用于接收传递给方法的变量值。调用方法时,必须严格按照参数的定义一一传递。

    public void setNameAndAge(String name, int age) {
        ...
    }

可变参数
可变参数用类型…定义,可变参数相当于数组类型

class Group {
    private String[] names;

    public void setNames(String... names) {
        this.names = names;
    }
}
Group g = new Group();
g.setNames("Xiao Ming", "Xiao Hong", "Xiao Jun"); // 传入3个String
g.setNames("Xiao Ming", "Xiao Hong"); // 传入2个String
g.setNames("Xiao Ming"); // 传入1个String
g.setNames(); // 传入0个String

参数绑定
调用方把参数传递给实例方时,调用时传递的值会按照参数位置一一绑定

// 基本类型
public class Main {
    public static void main(String[] args) {
        Person p = new Person();
        int n = 15; // n的值为15
        p.setAge(n); // 传入n的值
        System.out.println(p.getAge()); // 15
        n = 20; // n的值改为20
        System.out.println(p.getAge()); // 15还是20? ---> 15
    }
}

class Person {
    private int age;

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

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

修改外部的局部变量n,不影响实例p的age字段,原因是setAge()方法获得的参数,复制了n的值,因此,p.age和局部变量n互不影响。

// 引用类型
public class Main {
    public static void main(String[] args) {
        Person p = new Person();
        String[] fullname = new String[] { "Homer", "Simpson" };
        p.setName(fullname); // 传入fullname数组
        System.out.println(p.getName()); // "Homer Simpson"
        fullname[0] = "Bart"; // fullname数组的第一个元素修改为"Bart"
        System.out.println(p.getName()); // "Homer Simpson"还是"Bart Simpson"?---->"Bart Simpson"
    }
}

class Person {
    private String[] name;

    public String getName() {
        return this.name[0] + " " + this.name[1];
    }

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

引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方(因为指向同一个对象)。

// 引用类型
public class Main {
    public static void main(String[] args) {
        Person p = new Person();
        String bob = "Bob";
        p.setName(bob); // 传入bob变量
        System.out.println(p.getName()); // "Bob"
        bob = "Alice"; // bob改名为Alice
        System.out.println(p.getName()); // "Bob"还是"Alice"?---->"Bob"
    }
}

class Person {
    private String name;

    public String getName() {
        return this.name;
    }

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

解释
在这里插入图片描述在这里插入图片描述

构造方法

在创建对象实例时就把内部字段初始化为合适的值?需要构造方法。

在创建Person实例的时候,一次性传入name和age

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Xiao Ming", 15);
        System.out.println(p.getName());
        System.out.println(p.getAge());
    }
}

class Person {
    private String name;
    private int age;

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

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

和普通方法相比,构造方法没有返回值,也没有void,调用构造方法,必须用new操作符

默认构造方法

任何class都要构造方法

如果一个类没有定义构造方法,编译器会自动为我们生成一个默认构造方法,它没有参数,也没有执行语句

class Person {
    public Person() {
    }
}

如果自定义了一个构造方法,编译器就不再自动创建默认构造方法

如果既要能使用带参数的构造方法,又要保留不带参数的构造方法,要把两个方法都定义出来

多构造方法

可以定义多个构造方法,在通过new操作符调用的时候,编译器通过构造方法的参数数量、位置和类型自动区分

class Person {
    private String name;
    private int age;

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

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

    public Person() {
    }
}

一个构造方法可以调用其他构造方法,这样便于代码复用,调用其他构造方法的语法是this(…)

class Person {
    private String name;
    private int age;

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

    public Person(String name) {
        this(name, 18); // 调用另一个构造方法Person(String, int)
    }

    public Person() {
        this("Unnamed"); // 调用另一个构造方法Person(String)
    }
}

方法重载

在一个类中,可以定义多个方法。如果有一系列方法,功能都是类似的,只有参数有所不同,那么,可以把一组方法名做成同名方法

class Hello {
    public void hello() {
        System.out.println("Hello, world!");
    }

    public void hello(String name) {
        System.out.println("Hello, " + name + "!");
    }

    public void hello(String name, int age) {
        if (age < 18) {
            System.out.println("Hi, " + name + "!");
        } else {
            System.out.println("Hello, " + name + "!");
        }
    }
}

这种方法名相同,但各自的参数不同,称为方法重载(Overload)

方法重载的返回值类型通常都是相同的

继承

继承是面向对象编程中非常强大的一种机制,可以复用代码,Java使用extends关键字来实现继承

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student extends Person {
    // 不要重复name和age字段/方法,
    // 只需要定义新增score字段/方法:
    private int score;

    public int getScore() {}
    public void setScore(int score) {}
}

Person称为超类super class,父类parent class,基类base class,把student称为子类subclass,扩展类extended class

继承树
在Java中,没有明确写extends的类,编译器会自动加上extends Object。所以,任何类,除了Object,都会继承自某个类。

在这里插入图片描述

Java只允许一个class继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,它没有父类。

protected

继承中,子类无法访问父类的private字段或者private方法,这使得继承的作用被削弱。
为了让子类可以访问父类的字段,需要把private改为protected,用protected修饰的字段可以被子类访问

protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问。

super
super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName。

class Student extends Person {
    public String hello() {
        return "Hello, " + super.name;
    }
}

阻止继承
正常情况下,只要某个class没有final修饰符,那么任何类都可以从该class继承。

从Java 15开始,允许使用sealed修饰class,并通过permits明确写出能够从该class继承的子类名称。

public sealed class Shape permits Rect, Circle, Triangle {
    ...
}

多态

class Person {
    public void run() {
        System.out.println("Person.run");
    }
}
class Student extends Person {
    @Override
    public void run() {
        System.out.println("Student.run");
    }
}

抽象类

如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法

定义抽象方法,类也要定义为抽象类

abstarct class Person{
	public abstarct void run();
}

抽象类无法实例化,只能用于被继承,可以强迫子类实现其定义的抽象方法,否则编译会报错。抽象方法实际上相当于定义了“规范”。

接口

在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现,这样,多态就能发挥出威力。

如果一个抽象类没有字段,所有方法全部都是抽象方法,就可以把该抽象类改写为接口:interface。

interface Person {
    void run();
    String getName();
}

interface,就是比抽象类还要抽象的纯抽象接口,因为它连字段都不能有。因为接口定义的所有方法默认都是public abstract的,所以这两个修饰符不需要写出来(写不写效果都一样)。

当一个具体的class去实现一个interface时,需要使用implements关键字。

class Student implements Person {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(this.name + " run");
    }

    @Override
    public String getName() {
        return this.name;
    }
}

java中,一个类只能继承自另一个类,不能从多个类继承,但是,一个类可以实现多个interface

class Student implements Person, Hello { // 实现了两个interface
    ...
}

接口继承

interface Hello {
    void hello();
}

interface Person extends Hello {
    void run();
    String getName();
}

静态字段和静态方法

在一个class中定义的字段,称之为实例字段。实例字段的特点是,每个实例都有独立的字段,各个实例的同名字段互不影响。

还有一种字段,是用static修饰的字段,称为静态字段:static field。

实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段。

class Person {
    public String name;
    public int age;
    // 定义静态字段number:
    public static int number;
}

Java中使用包package来解决名字冲突

一个类总属于某个包,类名只是一个简写,真正完整的类名是 包名.类名

包作用域
位于同一个包的类,可以访问包作用域的字段和方法。不用public、protected、private修饰的字段和方法就是包作用域。

作用域

public

定义为public的class、interface可以被其他任何类访问

private

定义为private的field、method无法被其他类访问
一个类内部的嵌套类拥有访问private的权限

public class Main {
    public static void main(String[] args) {
        Inner i = new Inner();
        i.hi();
    }

    // private方法:
    private static void hello() {
        System.out.println("private hello!");
    }

    // 静态内部类:
    static class Inner {
        public void hi() {
            Main.hello();
        }
    }
}

protected

protected作用于继承关系。定义为protected的字段可以被子类访问,以及子类的子类

package

包作用域是指一个类允许访问同一个package的没有public、private修饰的class,以及没有public、protected、private修饰的字段和方法

final

用final修饰class可以阻止被继承;
final修饰的method可以阻止被子类覆写;
final修饰field可以阻止被重新赋值;
final修饰局部变量可以阻止被重新赋值;

内部类

1、Inner class

class Outer {
    class Inner {
        // 定义了一个Inner Class
    }
}
Outer.Inner inner = outer.new Inner();

2、Anonymous class

不需要在Outer Class中明确地定义这个Class,而是在方法内部,通过匿名类(Anonymous Class)来定义。

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer("Nested");
        outer.asyncHello();
    }
}

class Outer {
    private String name;

    Outer(String name) {
        this.name = name;
    }

    void asyncHello() {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello, " + Outer.this.name);
            }
        };
        new Thread(r).start();
    }
}

3、Static Nested Class静态内部类

public class Main {
    public static void main(String[] args) {
        Outer.StaticNested sn = new Outer.StaticNested();
        sn.hello();
    }
}

class Outer {
    private static String NAME = "OUTER";

    private String name;

    Outer(String name) {
        this.name = name;
    }

    static class StaticNested {
        void hello() {
            System.out.println("Hello, " + Outer.NAME);
        }
    }
}

用static修饰的内部类和Inner Class有很大的不同,它不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this,但它可以访问Outer的private静态字段和静态方法。如果把StaticNested移到Outer之外,就失去了访问private的权限。

Inner Class和Anonymous Class本质上是相同的,都必须依附于Outer Class的实例,即隐含地持有Outer.this实例,并拥有Outer Class的private访问权限;
Static Nested Class是独立类,但拥有Outer Class的private访问权限。

写在最后

这些抄一遍好像也记不住,,,,还是要定期回顾。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1320392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

06. Python模块

目录 1、前言 2、什么是模块 3、Python标准库模块 3.1、os模块 3.2、datetime 模块 3.3、random模块 4、自定义模块 4.1、创建和使用 4.2、模块命名空间 4.3、作用域 5、安装第三方依赖 5.1、使用 pip 安装单个依赖 5.2、从 requirements.txt 安装依赖 5.3、安装指…

Python:(Sentinel-1)如何解析SNAP输出的HDF5文件并输出为GeoTIFF?

博客已同步微信公众号&#xff1a;GIS茄子&#xff1b;若博客出现纰漏或有更多问题交流欢迎关注GIS茄子&#xff0c;或者邮箱联系(推荐-见主页). Python&#xff1a;&#xff08;Sentinel-1&#xff09;如何解析SNAP输出的HDF5文件并输出为GeoTIFF&#xff1f; 01 前言 最近…

【NI-RIO入门】使用LabVIEW进行数据采集测量

于ni kb摘录 选择合适的编程模式 CompactRIO系统具有至少两个用户可选模式。某些CompactRIO型号具有附加的用户可选模式&#xff0c;可以在实时NI-DAQmx中进行编程。请参考本文以判断您的CompactRIO是否能够使用实时NI-DAQmx。将目标添加到项目后&#xff0c;将提示您选择要使…

TestSSLServer4.exe工具使用方法简单介绍(查SSL的加密版本SSL3或是TLS1.2)

一、工具使用方法介绍 工具使用方法参照&#xff1a;http://www.bolet.org/TestSSLServer/ 全篇英文看不懂&#xff0c;翻译了下&#xff0c;能用到的简单介绍如下&#xff1a; 将下载的TestSSLServer4.exe工具放到桌面上&#xff0c;CMD命令行进入到桌面目录&#xff0c;执…

Gitee基础知识

目录 1-gitee 1.1gitee介绍 1.2git与gitee的关系 1.3在国内为什么选择Gitee 2-注册与创建远程仓库 2.1注册 2.2创建远程仓库 2.3配置ssh公钥 2.3.1公钥的生成方法&#xff1a; 2.3.2 在gitee中配置公钥 2.3.4验证公钥 3-添加与推送远程仓库master 3.1基本命令…

78-C语言-完数的判断,以及输出其因子

简介&#xff1a;一个数如果恰好等于它的因子之和&#xff0c;这个数就称为完数&#xff0c;C语言编程找出1000之内的所有完数&#xff0c;并输出其因子。因子可以整除该数字的数&#xff0c; 如6的因子&#xff1a;1 2 3&#xff0c;6%10 6%20 6%30 解释全在注…

20 5G中高速列车通信:设计相关元素以减轻高移动性带来的影响

文章目录 一 、物理层设计1 DMRS2 CSI 和SRS3 PTRS4 多天线配置 二 初始接入三 目前面临困难 解决问题&#xff1a;列车高速移动&#xff0c;会使信道相干时间较短、多普勒频移和多普勒扩展较大等问题。为了在列车高速移动中解决这些问题&#xff0c;这篇文章概括了5G关键技术&…

掌动智能浅谈云网络流量分析的主要过程

在云计算时代&#xff0c;网络流量分析成为确保网络安全和性能的重要环节。随着企业和组织将应用和服务迁移到云平台&#xff0c;对云网络流量进行深入的分析变得至关重要。本文将介绍云网络流量分析的主要过程&#xff0c;以帮助读者更好地理解如何有效地监控和管理云环境中的…

MySQL进阶|MySQL中的事务(一)

文章目录 数据库事务MySQL中的存储引擎InnoDB存储引擎架构什么是事务事务的状态总结 数据库事务 MySQL 事务主要用于处理操作量大&#xff0c;复杂度高的数据。比方我想要删除一个用户&#xff08;销户&#xff09;以及这个用户的个人信息、订单信息以及其他信息&#xff0c;这…

对JVM内存模型的理解

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

MySQL主从复制详解

目录 1. 主从复制的工作原理 1.1. 主从复制的角色 1.2. 主从复制的流程 2. 配置MySQL主从复制 2.1. 确保主服务器开启二进制日志 2.2. 设置从服务器 2.3. 连接主从服务器 2.4. 启动复制 3. 主从复制的优化与注意事项 3.1. 优化复制性能 3.2. 注意复制延迟 3.3. 处理…

干涉光学测试导论

1.用于光学测试的基本干涉仪 2。相移干涉术 3。专业光学测试 4。长波长干涉术 5。非球面试验 6。表面微观结构的测量 7。绝对测量 8。结束语 第1部分-光学测试用基本干涉仪 (1)双光束干涉 (2)菲佐干涉仪和特维曼-格林干涉仪 (3)测试平面和球面的基本技术 (4)球面的基本…

2020年度NPcon-容器与微服务实践峰会 回顾

一&#xff0c;会议基本信息 时间&#xff1a;12月16日14:00-17:00 地点&#xff1a;上海机遇星球&#xff08;上海市黄浦区南京西路389号明天广场裙楼2楼&#xff09; 电梯旁边的指示牌 会场现场 出来的时候&#xff0c;天快黑了 二&#xff0c;内容回顾 由四个讲座和一个…

(5)shell命令以及Linux的权限

写在前面 本章我们将重点讲解 Linux 权限&#xff0c;这是 Linux 基础部分中非常重要的一部分。内容比较干&#xff0c;我会稍稍正经些去讲解。话不多说&#xff0c;我们直接切入正题。 shell 命令及运行原理 严格意义上说的是一个操作系统&#xff0c;我们称之为 —— &…

【AI基础设施】智算场景的资源管理系统与未来展望

高性能计算与智算场景 首先澄清两个概念&#xff0c;高性能计算与智算场景&#xff0c;高性能计算主要是面向天气预测、生物计算、材料计算等场景&#xff0c;而最近几年很火的智算主要是面向AI场景的计算&#xff0c;如语音识别、图像识别、自动驾驶等场景&#xff0c;我们可…

Git 如何撤回已 Push 的代码

在日常的开发过程中&#xff0c;我们广泛利用Git进行版本控制。然而&#xff0c;有时我们可能会误将错误的代码推送到远程仓库&#xff0c;或者希望在本地返回到先前的某个版本以重新进行开发。 就像我个人的经历一样&#xff0c;我曾推送了一些我认为未来会非常有用的优化方案…

14:00面试,14:05就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到12月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40…

SQL进阶理论篇(十一):什么是MVCC?

文章目录 简介什么是MVCC快照读与当前读悲观锁的问题示例参考文献 简介 在MySQL中&#xff0c;默认的隔离级别是可重复读&#xff0c;可以解决脏读和不可重复读的问题&#xff0c;但不能解决幻读问题。如果想要解决幻读问题&#xff0c;就需要采用串行化的方式&#xff0c;通过…

数据结构——【万字文章+配图+代码】带你深入理解二叉树

1. 二叉树的概念 二叉树是一种有限集合&#xff0c;由根和左右子树构成&#xff0c;每个结点最多有两棵子树&#xff0c;且这两棵子树具有顺序关系 2. 二叉树的特殊情况&#xff1a; 2.1 满二叉树&#xff1a; 一个二叉树&#xff0c;如果每次的结点都达到最大值&#xff…

07-Eventing及实践

1 Knative Eventing的相关组件 Knative Eventing具有四个最基本的组件&#xff1a;Sources、Brokers、Triggers 和 Sinks 事件会从Source发送至SinkSink是能够接收传入的事件可寻址&#xff08;Addressable&#xff09;或可调用&#xff08;Callable&#xff09;资源 Knative S…