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

文章目录

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

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{// fieldpublic 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{// fieldprivate String name;private int age;
}

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

class Person{// fieldprivate 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的值为15p.setAge(n); // 传入n的值System.out.println(p.getAge()); // 15n = 20; // n的值改为20System.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改名为AliceSystem.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 {@Overridepublic 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;}@Overridepublic void run() {System.out.println(this.name + " run");}@Overridepublic 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() {@Overridepublic 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.hqwc.cn/news/284735.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows phpstudy vscode Xdebug调试无效,无法监听,没有什么效果

Windows phpstudy vscode Xdebug调试无效&#xff0c;无法监听&#xff0c;没有什么效果 vscode 正常&#xff0c;能启动&#xff0c;能标记&#xff0c;就是无法监听 打印phpinfo(); Xdebug版本3 打印的信息输入这里&#xff0c;找出对应PHPXdebug的dll文件 Xdebug: Sup…

汽车火花塞行业分析:全球市场需求量约为26.3亿个

在汽车日常保养里,更换火花塞算是比较常见的一种,爱车懂车的车主们都非常清楚火花塞对于汽车的重要性,可以说火花塞直接影响到发动机的运作,决定了汽车能否顺利启程。 火花塞(sparkplug)&#xff0c;俗称火咀&#xff0c;它的作用是把高压导线(火嘴线)送来的脉冲高压电放电&…

运维实践|采集MySQL数据出现many connection errors

文章目录 问题出现问题分析当前环境问题分析 解决方案1 检查调度事件任务是否开启2 开启调度事件任务3 创建一张日志表4 创建函数存储过程5 创建事件定时器6 开启事件调度任务7 检查核实是否创建 总结 问题出现 最近在做OGG结构化数据采集工作&#xff0c;在数据采集过程中&am…

【剪映】点滴剪时光

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

双指针算法(二)

三数之和 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重…

Go环境安装

目录 下载地址 安装 macos环境 window及其他环境 GOPROXY 非常重要 Go开发编辑器 下载地址 Go官网下载地址&#xff1a;https://golang.org/dl/ Go官方镜像站&#xff08;推荐&#xff09;&#xff1a;https://golang.google.cn/dl/ 选择要下载的系统版本&#xff1a; 安装 注意…

DataGrip 2023.3 新功能速递!

1 数据可视化 自 DataGrip 2023.3 发布以来&#xff0c;已整合 Lets-Plot 库&#xff0c;实现数据可视化。该可视化功能可用于所有三种类型的网格&#xff1a; 主选项卡&#xff1a;在打开表、视图或 CSV 文件时&#xff0c;在分割模式下显示图表。结果选项卡&#xff1a;在 服…

计算机组成原理(输入输出系统-----程序查询方式)

目录 程序查询方式 一.程序查询方式的流程 1.查询流程 2.程序流程 二.程序查询方式的接口电路 程序查询方式 一.程序查询方式的流程 1.查询流程 单个设备&#xff1a; 如果在传输过程当中只有一个内存和I/O之间数据传输&#xff0c;在执行程序的过程当中CPU会执行出来一…

setXxx getXxx 封装

1.封装介绍 封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。 2.封装的理解和好处 (1)隐藏实现细节 方法(连接数据库)<-----调用(传入参数...) 只负责调…

代码随想录27期|Python|Day17|二叉树|110.平衡二叉树 |257. 二叉树的所有路径 |404.左叶子之和

110. 平衡二叉树 - 力扣&#xff08;LeetCode&#xff09; 在递归后序遍历的基础上加上一个中间节点判断左右子节点的高度的步骤即可。 具体实现 是如果左右子树已经高度差大于1&#xff0c;则中间节点标记为-1&#xff0c;在逐层向上返回之后可以在root节点被判定为false&am…

力扣---最长回文子串(动态规划)

目录 ​编辑 题目 思路步骤&#xff1a; 代码 我的其他博客 题目 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&…

详解git pull和git fetch的区别

git pull和git fetch的区别, 网上人云亦云胡说八道的实在是太多了&#xff0c;误导我很久。 今天看到一个说得好的&#xff0c;记录一下。 前言 在我们使用git的时候用的更新代码是git fetch&#xff0c;git pull这两条指令。但是有没有小伙伴去思考过这两者的区别呢&#xff…