Java面向对象编程

2023-10-30

第一章 类与对象

面向对象简介

面向过程指的是面对于一个问题的解决方案,更多情况下不会做出重用的设计。

面向对象主要设计形式为模块化设计,可以进行重用配置,更多情p况下考虑的是标准,然后根据标准进行拼装。

面向对象有三个主要特性:

封装性:内部的操作对外部不可见,当内部的操作都不可直接使用的时候才是安全的;

继承性:在已有结构的基础上继续进行功能的扩充;

多态性:在继承性的基础上扩充而来的概念,指的是类型的转换处理。

面向对象程序开发的步骤:

        OOA:面向对象分析;OOD:面向对象设计;OOP:面向对象编程。

类与对象简介

类是对某一类事物共性的抽象概念。

对象描述的是一个具体的产物。

类是一个模板,而对象是类的实例,所以先有类才有对象。(类比为船的图纸(类)与船(对象),根据图纸可以造很多船)

类的组成:

        成员属性(Field):简化称为”属性“,其对象的特征(人的姓名、人的年龄...),属性是指描述对象的一组数据,表现为对象的一些变量。

        操作方法(Method):表示对象的行为或所作的工作。

类与对象的定义及使用

Java中类是一个独立的结构体,所以需要用class来定义

public class Student {
    // 类的属性:成员变量
    String name;
    int age;
    String like;

    // 成员方法(实例方法)
    public void show(){
        System.out.println("我叫"+name+",今年"+age+",我的爱好"+like);
    }
    // main方法
    public static void main(String[] args) {
        Student stu = new Student(); //创建对象,通过类来创建对象 new 类名()
        stu.name = "张三"; // 调用成员变量赋值:对象名.属性名
        stu.age = 20;
        stu.like = "干饭";
        stu.show(); // 调用成员方法
    }
}

语法:

        产生对象:

        一步完成: 声明并实例化对象:类名称 对象名称 = new 类名称();

        分步完成: 声明对象:类名称 对象名称 = null;

                           实例化对象:对象名称 = new 类名称();

        调用: 类中的属性:对象名称.成员属性

                    类中的方法:对象名称.方法名称()

如果程序没有进行对象属性内容的设置,则数据内容为其对应数据类型的默认值。

对象内存分析

Java中类属于引用数据类型,困难之处在于要进行内存的管理。所以对内存管理进行简单分析。

最常用的内存空间:

堆内存:保存对象的具体信息,在程序中堆内存空间的开辟是通过new完成的;

栈内存:保存单块堆内存的地址。即:通过通过地址找到堆内存,而后找到对象内容。但是为了分析简化起见,可以简单的理解为:对象名称保存在了栈内存之中。

直接声明并实例化对象的内存分析:

class Person { // 定义一个类
	String name; // 人的姓名
	int age; // 人的年龄
	public void tell() {
		System.out.println("姓名:" + name + ",年龄:" + age);
	}
}
public class JavaDemo { 
    public static void main(String[] args) { 
        Person per = new Person(); // 声明并实例化对象 
        per.name = "张三"; 
        per.age = 18; 
        per.tell(); // 进行方法的调用 
    } 
}  

 分步骤声明再实例化对象的内存分析

public class JavaDemo {
	public static void main(String[] args) {
		Person per = null; // 声明对象
		per = new Person(); // 实例化对象
		per.name = "张三";
		per.age = 18;
		per.tell(); // 进行方法的调用
	}
}

所有调用类的属性和方法在实例化对象完成后才能执行,调用只声明但没有实例化的对象

public class JavaDemo {
	public static void main(String[] args) {
		Person per = null; // 声明对象
		per.name = "张三";
		per.age = 18;
		per.tell(); // 进行方法的调用
	}
}

上述代码会产生“java.lang.NullPointerException”的空指向异常,因为此时并没有在堆内存中开辟空间,这种情况只发生于引用数据类型。

对象引用分析

由于类属于引用数据类型,因此就牵扯到内存的引用传递。

引用传递:指同一块堆内存被不同的栈内存所指向。

在主方法中使用引用传递:

public class JavaDemo {
	public static void main(String[] args) {
		Person per1 = new Person(); // 声明并实例化对象
		per1.name = "张三";
		per1.age = 18;
		Person per2 = per1; // 引用传递
		per2.age = 80;
		per1.tell(); // 进行方法的调用
	}
}

利用方法实现引用传递:

与之前的差别最大的地方在于,此时的程序是将Person类的实例化对象(内存地址、属性的参数)传递到了change()方法中,由于传递的是一个Person对象类型,那么change()接收的也是Person类型。  

public class JavaDemo {
	public static void main(String[] args) {
		Person per = new Person(); // 声明并实例化对象
		per.name = "张三";
		per.age = 18;
		change(per); // 等价于:Person temp = per;
		per.tell(); // 进行方法的调用
	}
	public static void change(Person temp) {
		temp.age = 80;
	}
}

 引用传递可以发生在方法上,要观察方法里面传的的参数类型,同时也要观察方法的执行过程。

引用与垃圾产生分析

引用传递的本质:一场堆内存的调戏游戏。但引用传递,引用不当会产生垃圾。对垃圾产生原因进行简单分析。

public class JavaDemo {
	public static void main(String[] args) {
		Person per1 = new Person(); // 声明并实例化对象
		Person per2 = new Person();
		per1.name = "张三";
		per1.age = 18;
		per2.name = "李四";
		per2.age = 19;
		per2 = per1; // 引用传递
		per2.age = 80;
		per1.tell(); // 进行方法的调用
	}
}

 垃圾空间:没有任何栈内存所指向的堆内存空间,所有的垃圾都将被GC(Garbage Collector:垃圾收集器)不定期进行回收,并且释放无用空间,但如果垃圾过多,一定将影响到GC的处理性能,从而降低整体的程序性能。

一个栈内存只能够保存一个堆内存的地址数据,如果发生更改,则之前的地址数据将从此栈内存中彻底消失。

第二章 深入分析类与对象

成员属性封装

类的组成就是属性与方法,一般而言方法都是对外提供服务的,所以是不会进行封装处理的;而属性需要较高的安全性,所以就需要封装性对属性进行保护。

对属性进行封装:使用private关键字。

class Person { // 定义一个类
	private String name; // 人的姓名
	private int age; // 人的年龄
	public void tell() {
		System.out.println("姓名:" + name + ",年龄:" + age);
	}
}

属性一旦封装后,外部将不可以直接进行访问。

【setter、getter】设置或取得属性使用setXxx()、getXxx()方法。

设置属性方法:public void setName(String name) {};

获取属性方法:public String getName() {};

class Person { // 定义一个类
	private String name; // 人的姓名
	private int age; // 人的年龄
	public void tell() {
		System.out.println("姓名:" + name + ",年龄:" + age);
	}
	public String getName() {
        return name;
    }
    public void setName(String newName) {
        name = newName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int newAge) {
        age = newAge;
    }
}
public class JavaDemo {
	public static void main(String[] args) {
		Person per = new Person(); // 声明并实例化对象
		per.setName("张三"); // 在类外部通过方法修改私有属性
		per.setAge(18);
		per.tell(); // 进行方法的调用
	}
}

在定义类时,属性都应该使用private封装(98%),并提供setter、getter方法。

构造方法与匿名对象

现在的程序在使用类的时候一般都按照了如下的步骤进行:

声明并实例化对象,这个时候实例化对象中的属性并没有任何的的数据存在,都是其对应数据类型的默认值。

需要通过一系列的setter()方法设置属性值

public class JavaDemo{ // 主类
​	public static void main(String args[]){
​		// 1、对象初始化准备
​		Person per = new Person(); // 声明并实例化对象
​		per.setName("张三");
​		pei.setAge(-18); // 在类外部修改属性
​		// 2、对象的使用
​		per.tell(); // 进行方法的调用
​	}
}

假设现在类中的属性有很多个,按上述方法,需要调用多次setter方法进行设置,过于麻烦,所有提供构造方法,实现实例化对象中的属性初始化处理。

构造方法作用:实现实例化对象中的属性初始化处理。 使用:通过new关键字进行实现(因为实例化对象就是通过new关键字实现的)。

定义要求:

        构造方法名称必须与类名称一致;

        构造方法不允许设置返回值类型,即:没有返回值定义;

        构造方法时在使用new关键字实例化对象时自动调用的。         

class Person { // 定义一个类
	private String name; // 人的姓名
	private int age; // 人的年龄
	public Person(String n, int a) { // 定义有参构造
        name = n; // 为类中的属性赋值(初始化)
        age = a; // 为类中的属性赋值(初始化)
    }
	public void tell() {
		System.out.println("姓名:" + name + ",年龄:" + age);
	}
}
public class JavaDemo { // 主类
	public static void main(String[] args) {
		// 1、对象初始化准备
		Person per = new Person("张三", 18); // 声明并实例化对象
		// 2、对象的使用
		per.tell(); // 进行方法的调用
	}
}

实例化对象例子对比:

        之前:①Person ②per= ③new ④Person()

        当前:①Person ②per= ③new ④Person(“张三”, 18)

解析:

        ①Person:定义对象的所属类型,类型决定了可以调用的方法;

        ②per=:实例化对象的名称,所有的操作通过对象来进行访问;

        ③new:开辟一块新的堆内存空间;

        ④Person():调用无参构造; ④Person(“张三”, 18):调用有参构造。

在Java程序里面考虑到程序结构的完整性,所以所有的类都会提供有构造方法,如果你的类中没有定义的构造方法,那么程序会默认提供无参的构造方法,这个是在程序编译时自动创建的;

如果你的类中有定义构造方法,那么程序则不会自动提供无参的构造方法。所以一个类至少存在有一个构造方法,且永恒存在。

疑问:为什么构造方法上不允许设置返回值类型?

程序编译器是根据代码结构来进行编译处理的,执行时也是根据代码结构来处理的。

因此如果设置了返回值类型,那么构造方法的结构与普通方法的结构完全相同,这样编译器会认为此方法时一个普通方法。

普通方法与构造方法最大的区别:构造方法是在类对象实例化时调用的,而普通方法是在类对象实例化产生之后才可以调用的。

构造方法本身就是一个方法,其具有重载的特点,而构造方法重载的时候只需要考虑参数的类型及个数即可。

进行多个构造方法定义的时候可以有定义的顺序,如按照参数的个数降序或升序进行。

构造方法可以进行数据的设置,而setter也可以进行数据的设置。构造方法是在对象实例化的时候为属性设置初始化内容,而setter还拥有修改数据的内容。

匿名对象:直接实例化对象来进行类的操作(没有声明对象,所以对象是没有名字的)。

public class JavaDemo { // 主类
	public static void main(String[] args) {
		new Person("张三", 10).tell(); // 通过匿名对象直接进行方法的调用
	}
}

通过匿名对象调用方法,由于此对象没有任何的引用名称,因此该对象在使用一次之后就成为了垃圾,而所有的垃圾都将被GC进行回收与释放。

通过以下程序,进行简短的内存分析。

class Message{
	private String title;
	public Message(String t) {
		title = t;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String t) {
		title = t;
	}
}
class Person{
	private String name;
	private int age;
	public Person(Message msg,int a ) {
		name = msg.getTitle();
		age = a;
	}
	public Message getInfo(){
		return new Message(name + ":" + age)
	}
	public void tell() {
		System.out.println("姓名" + name + "年龄" + age);
	}
}
public class No1PersonMessage {
	public static void main(String args[]) {
		Message msg = new Message("mldn");
		Person per = new Person(msg,20);
		msg = per.getInfo();
		System.out.println(msg.getTitle());
	}	
}

 只要是方法都可以传递任意的数据类型(基本数据类型、引用数据类型)。

this关键字

this可以实现以下三类 结构的描述:

        当前类中的属性:this.属性名;

        当前类中的方法:构造方法:this();普通方法:this.方法名();

        描述当前对象;

在Java程序中,“{}”是作为一个结构体的边界符,所以在程序里面当进行变量(参数 / 属性)使用时,都会以“{}”作为查找边界。按照就近取用的原则,此时的构造方法并没有能够访问类中的属性,所以为了明确标记类中的属性和参数的区别,往往会在属性前追加一个this,表示本类的属性。

只要是访问本类中的属性的时候,都要加this。

class Person {
	private String name;
	private int age;
	public Person(String name, int age) {
        this.name = name;
        this.age = age
    }
	public void tell() {
		System.out.println("姓名:" + this.name + ",年龄:" + this.age);
	}
}

待续。。。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java面向对象编程 的相关文章

  • 不同帐户上的 Spring Boot、JmsListener 和 SQS 队列

    我正在尝试开发一个 Spring Boot 1 5 应用程序 该应用程序需要侦听来自两个不同 AWS 帐户的 SQS 队列 是否可以使用 JmsListener 注解创建监听器 我已检查权限是否正确 我可以使用 getQueueUrl 获取
  • Junit:如何测试从属性文件读取属性的方法

    嗨 我有课ReadProperty其中有一个方法ReadPropertyFile返回类型的Myclass从属性文件读取参数值并返回Myclass目的 我需要帮助来测试ReadPropertyFile方法与JUnit 如果可能的话使用模拟文件
  • 如何通过 javaconfig 使用 SchedulerFactoryBean.schedulerContextAsMap

    我使用 Spring 4 0 并将项目从 xml 移至 java config 除了访问 Service scheduleService 带注释的类来自QuartzJobBean executeInternal 我必须让它工作的 xml 位
  • 在内存中使用 byte[] 创建 zip 文件。 Zip 文件总是损坏

    我创建的 zip 文件有问题 我正在使用 Java 7 我尝试从字节数组创建一个 zip 文件 其中包含两个或多个 Excel 文件 应用程序始终完成 没有任何异常 所以 我以为一切都好 当我尝试打开 zip 文件后 Windows 7 出
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 来自 dll 的 Java 调用函数

    我有这个 python 脚本导入zkemkeeperdll 并连接到考勤设备 ZKTeco 这是我正在使用的脚本 from win32com client import Dispatch zk Dispatch zkemkeeper ZKE
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • Hibernate 的 PersistentSet 不使用 hashCode/equals 的自定义实现

    所以我有一本实体书 public class Book private String id private String name private String description private Image coverImage pr
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • 内部类的构造函数引用在运行时失败并出现VerifyError

    我正在使用 lambda 为内部类构造函数创建供应商ctx gt new SpectatorSwitcher ctx IntelliJ建议我将其更改为SpectatorSwitcher new反而 SpectatorSwitcher 是我正
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • logcat 中 mSecurityInputMethodService 为 null

    我写了一点android应显示智能手机当前位置 最后已知位置 的应用程序 尽管我复制了示例代码 并尝试了其他几种解决方案 但似乎每次都有相同的错误 我的应用程序由一个按钮组成 按下按钮应该log经度和纬度 但仅对数 mSecurityInp
  • 为什么 Java 8 不允许非公共默认方法?

    让我们举个例子 public interface Testerface default public String example return Hello public class Tester implements Testerface
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • Spring Boot 无法更新 azure cosmos db(MongoDb) 上的分片集合

    我的数据库中存在一个集合 documentDev 其分片键为 dNumber 样本文件 id 12831221wadaee23 dNumber 115 processed false 如果我尝试使用以下命令通过任何查询工具更新此文档 db

随机推荐

  • 我在偷偷学Python的第二十七天(正则表达式----下)

    正则表达式介绍 re RegexObject re compile 返回 RegexObject 对象 re MatchObject group 返回被 RE 匹配的字符串 start 返回匹配开始的位置 end 返回匹配结束的位置 spa
  • 搞定VS中反复弹出 Enterprise Core Objects 注册的问题

    搞定VS中反复弹出 Enterprise Core Objects 注册的问题 参照 http blog vichamp com 2007 11 vs2008eco html http capableobjects com node 69
  • OKR概述

    OKR很难吗 用一张图告诉你OKR的定义 操作方法 谷歌实操步骤等 让你快速对OKR有一个全面了解 什么是OKR 中文是目标与关键结果法 是Object ives and Key Results的英文缩写 定义 这是一种由公司 团队和个人协
  • 解决微信自定义图文分享不成功

    首先用到微信开放平台的JS SDK 准备工作 1 用来绑定的微信公众号必须是已认证的 2 链接地址必须是域名 并且是备案过的 当然就得需要服务器了 配置工作 1 配置分享的JS接口安全域名 不然前端配分享时会报错 config invali
  • C++将OpenCV的Mat数据保存为本地.xyz格式,并重新读取为Mat格式

    一 问题 需要将一个OpenCV的Mat格式数据保存到本地为 xyz文件 可用记事本打开 其数据类型为64FC1 数据中包含NaN值 此外还需要将其重新读取为Mat 要求NaN值可以准确识别 二 代码 include
  • Java实现多附件的邮件发送

    叙 本文主要记述了 Springboot 中如何集成并实现多附件的邮件发送 以QQ邮箱的服务器为发送邮件的邮件服务器 Java实现多附件的邮件发送 1 前期准备 1 1 获取收发服务器地址及其端口号 1 2 授权码的获取 2 代码 2 1
  • QTCreator在Ubuntu安装及运行程序报错解决

    1 QT Creator安装 软件包下载 可以进入官网下载或者使用wget命令下载 个人使用wget命令安装如下 sudo wget http download qt io archive qt 5 12 5 12 9 qt opensou
  • VScode修改行间距

    在我们编码的过程中 由于显示字体和显示器的不同 会需要调整行间距 在vscode默认的选项中没有看到设定行间距的选项 不过 可以手动修改配置档达到目的 1 打开设置 2 打开配置档 手动进行设定 3 在选项中添加 editor lineHe
  • Kafka中Producer源码解读

    Producer源码解读 在 Kafka 中 我们把产生消息的一方称为 Producer 即 生产者 它是 Kafka 的核心组件之一 也是消息的来源所在 它的主要功能是将客户端的请求打包封装发送到 kafka 集群的某个 Topic 的某
  • Qt极简贪吃蛇实现

    持续修正更新该项目 环境 Qt 4 8 Qt5环境也可使用 全部文件传送门 部分重要模块代码 include snakegame h include ui snakegame h SnakeGame SnakeGame QWidget pa
  • 连接SQL Server 数据库

    目录 一 启动 SQL Server Management Studio 1 点击 SQL Server Management Studio 菜单进入 2 选择服务器和身份验证方式 3 点击连接进入数据库 二 新建数据库 1 数据库的概念
  • 6370小时时,在公司稳定兼职(4000/月)(2016年5月2日 PS:实际上并不是稳定兼职,没项目了就没钱了。)

    周六时 兼职的公司要去了我的工行卡号 以后每月打4000到我的卡里 我需要调整规划了 2016年5月2日 PS 实际上并不是稳定兼职 没项目了就没钱了
  • Linux C文件IO操作

    文件IO 在Linux中万物都为文件 普通文件 设备 socket 标准输入输出等等 常用接口 Method Parameters Descriptions Return H open char name int flags mode 打开
  • python学习3.1

    一 if 语句的使用 if 后的语句是否执行 也跟缩进有关 1 if else eg 输入 bands oasis the beatles eagles the who the kinks for band in bands if band
  • Alist搭建

    Alist简介 一个支持多种存储的文件列表程序 AList设计易于安装 可以在所有平台上使用 支持多个存储提供商 包括本地存储 阿里云盘 OneDrive Google Drive 等 且易于拓展 支持所有 WebDAV 存储 支持视频 音
  • Python tkinter如何把窗口在屏幕中央居中

    Python tkinter如何把窗口在屏幕中央居中 coding utf 8 import tkinter as tk 创建 Tkinter 窗口 root tk Tk 设置窗口大小 root geometry 400x300 获取屏幕宽
  • 企业微信消息多久可以撤回?企业微信怎么查看撤回的消息?

    大家都知道 个人微信是可以撤回两分钟以内的消息 超过两分钟就无法撤回了 那企业微信可以撤回发送了多久的消息呢 撤回的消息还能够查看吗 跟着企业微信服务商艾客scrm小编 一起来看看吧 其实 我们使用任何一个聊天工具聊天的过程中 撤回消息在所
  • Unity URP渲染管线与内置渲染管线的性能差别

    首先 我们来了解一下Unity的内置渲染管线 内置渲染管线是Unity较早版本中使用的默认渲染管线 它使用的是传统的图形渲染技术 内置渲染管线提供了一系列的渲染功能 如阴影 反射 抗锯齿等 但是 由于其较为庞大且复杂的设计 它的性能相对较低
  • qt动态显示当前时间如何实现

    Qt qt动态显示当前时间如何实现 vestinfo 1 票 182 include mainwindow h include ui mainwindow h include
  • Java面向对象编程

    第一章 类与对象 面向对象简介 面向过程指的是面对于一个问题的解决方案 更多情况下不会做出重用的设计 面向对象主要设计形式为模块化设计 可以进行重用配置 更多情p况下考虑的是标准 然后根据标准进行拼装 面向对象有三个主要特性 封装性 内部的