05 Java 类和对象

本文涉及的产品
访问控制,不限时长
简介: 面向对象是 Java 最重要的特性。Java 是彻底的、纯粹的面向对象语言,在 Java 中“一切都是对象”。本章将介绍面向对象基础知识。面向对象• 相对面向过程而言, 面向对象和面向过程都是一种思想• 将功能封装进对象,强调具备了功能的对象。• 是一种符合人们思考习惯的思想, 可以将复杂的事情简单化, 将程序员从执行者转换成了指挥者.

面向对象是 Java 最重要的特性。Java 是彻底的、纯粹的面向对象语言,在 Java 中“一切都是对象”。本章将介绍面向对象基础知识。

面向对象


  • 相对面向过程而言, 面向对象和面向过程都是一种思想


  • 将功能封装进对象,强调具备了功能的对象。


  • 是一种符合人们思考习惯的思想, 可以将复杂的事情简单化, 将程序员从执行者转换成了指挥者.


面向对象的开发过程: 其实就是不断的创建对象,使用对象,指挥对象做事情。


面向对象的设计过程: 其实就是在管理和维护对象之间的关系。


面向对象的特征:


  • 封装(encapsulation): 封装能够使外部访问者不能随意存取对象的内部数据,隐藏了对象的内部细节,只保留有限的对外接口。外部访问者不用关心对象的内部细节,使得操作对象变得简单。


  • 继承(inheritance)


  • 多态(polymorphism): 指在父类中成员变量和成员方法被子类继承之后,可以具有不同的状态或表现行为。


什么是类



Java中用类 Class 来描述事物.是具体事物的抽象,概念上的定义。


  • 属性:对应类中的成员变量。


  • 行为:对应类中的成员函数。


类定义包括类声明和类体两部分,类定义的语法格式如下:


[public][abstract|final] class className [extends superclassName] [implements interfaceNameList] {类体}


对象的创建



创建对象及访问对象成员


  1. 声明对象与声明普通变量没有区别 ,格式为type objectName; 
    声明对象并不为对象分配内存空间,而只是未存储对象的地址分配内存空间


  1. 实例化对象。分为两个阶段:为对象分配内存空间和初始化对象,首先使用new运算符为对象分配内存空间,然后再调用构造方法初始化对象。格式如下:new 类的构造方法();


  1. 通过引用变量访问对象成员


  • 引用变量名.属性


  • 引用变量名.方法名(实参表)


什么是方法


方法声明


修饰符 1 修饰符2... 返回值类型 方法名(形参表) [ throws 异常列表 ] { }

其中返回值是方法在操作完成后返还调用它的环境的数据,形式有2种:


  1. return 表达式; // 方法返回结果为表达式的值;


  1. return;            // 用于无返回值的方法退出,无返回值末尾可不写;


参数传递


  1. 基本数据类型的参数传递是以传值的方式进行,即将实际参数的值传递给形参;  在方法内对形参的修改只影响形参单元,不影响实参


  1. 引用类型(如对象、数组等)参数传递是按地址进行传递的。在方法内对形参的访问实际是访问所指引用对象


方法的特点:


将功能代码进行封装,便于对该功能进行调用。只有被调用才被执行,提高了代码的复用性. (注意不能在函数的内部定义方法) 。


方法的重载(Overload):


  • 在同一个类中,允许存在一个以上的同名函数,函数参数个数或类型至少其一不同.


  • 由于只考虑参数类型和个数的差异  ,不考虑出现返回值类型的差异. 因为这将导致算法的不确定性,这是不可能存在的。强烈建议重载其返回值类型相同


  • 方法调用的匹配处理原则是,首先按“精确匹配”原则去查找匹配方法,如果找不到,则按“自动类型转换匹配”原则去查找能匹配的方法。


  • 所谓“精确匹配”就是实参和形参类型完全一致


  • 所谓“自动转换匹配”是指虽然实参和形参类型不同,但能将实参的数据按自动转换原则赋值给形参。


mybatis 的 SQL 操作方法签名不支持重载。


方法的覆盖(Override)


  • 方法名、参数列表、完全相同才会产生方法覆盖;


  • 返回类型通常也要一致,只有返回类型为引用类型时,允许子类方法的返回类型是父类方法返回类型的子类型。


  • 覆盖不能改变方法的静态与非静态属性。子类中不能将父类非静态方法定义为静态方法,反之也一样。


  • final 方法不能被覆盖。


不允许子类方法的访问修饰符比父类有更多的限制。例如:子类不能将父类的 public 方法定义为 protected 方法。但可以将父类的 private 方法在子类中重新定义为 public 方法.通常将子类方法访问修饰符与父类保持一致.


构造方法


作用: 给对象进行初始化


构造方法的特点


  • 构造方法的名称必须与类名同名;


  • 构造方法没有返回类型, 包括void, 所以不可以写return语句;


  • 构造方法只能与 new 运算符结合使用;


  • 通常一个类可提供多个构造方法,这些方法的参数不同。在创建对象
    时,系统自动调用参数匹配的构造方法为对象初始化


  • 如果一个类未指定构造方法,则系统自动提供的无参构造方法,但如果自定义了构造方法,则系统不再提供无参构造方法
    无参构造方法形式如下: public Person() { } , 所以自己最好还要默默的加入无参构造方法


  • 什么时候定义构造方法: 当分析事物时, 该事物具备一定特性或行为, 可以将这些内容定义在构造方法中.


一个类默认有一个空参数的构造函数,这个构造函数的权限与所属类一致. 如果类被 public 修饰,则默认的构造函数也被 public 修饰.总之默认构造函数的权限是随着类而变化.


对象的初始化和构造方法


在创建对象时,要给对象的属性成员分配内存空间,同时进行初始化。


  1. 如果定义属性成员时没有指定初值,则系统自动指定初值.在定义属性成员时也可以指定初值.public class Point { private int x=10;    ……


  1. 指定初值的另一种办法是通过初始化块来设置对象的初值(也叫做构造代码块,它是给所有对象进行统一初始化)。
    // 注意首先是按照属性定义的初值,然后是初始化块,


  1. 最后是构造方法:构造方法是给对相关设置初值的规范方法,构造方法是根据方法参数给对象属性赋不同的值


成员变量


声明类体中成员变量语法格式如下:


[public | protected | private ] [static] [final] type variableName; //成员变量


成员方法


[public | protected | private ] [static] [final | abstract] [native] [synchronized] type methodName([paramList]) [throws exceptionList] { //方法体 }


static关键字



静态属性


用 static 修饰的属性是属于类的静态属性, 相应的成员变量为类变量


  1. 类变量的访问形式


  • 在本类中直接访问:count


  • 通过类名访问:User.count


  • 不建议通过类的一个对象访问,如:x1.count, 实际上还是通过类名的方式访问


  1. 给类变量赋初值
    默认赋值即可,也可以用静态初始化代码块 static{count=100;}
    // 静态初始化代码的执行是在main方法执行前完成。


  1. 被 static 修饰的类成员特点:是共享数据, 随着类的加载而加载, 优先于对象存在, 被所有对象所共享, 可以直接被类名调用.


静态方法


用 static 修饰的方法称为静态方法,也叫类方法. 在 static 方法中只能处理类变量,也可访问其它 static 方法,但不能访问任何归属对象空间的变量或方法.


而非静态成员变量和方法却可以访问静态资源.


  • 静态方法中不可以写 this,super 关键字


  • 主函数是静态方法.


tip: 创建某个工具类, 可只提供相应的静态方法, 进一步为了让某个类不能创建对象, 可以私有化构造函数.


理解 this 和 super


出现在类的实例方法或构造方法中,this 代表所在函数所属对象的引用。用 this 作前缀可访问当前对象的实例变量或成员方法.


  1. this.实例变量; // 能加 this 则尽量加, 这样代码更清晰


  1. this.成员方法; // 本类成员方法的调用, 能加 this 则尽量加 this


  1. this(参数),用来调用同类其他构造方法.注意 this 语句只能定义在构造函数的第一行,因为初始化要先执行.


super关键字则和 this 差不多,都是一个引用指向自身和上一级父类罢了.


this()构造的此类用法, 可以减少构造的一些重复代码

public Msg() {
  this(0, null, -1);
}
public Msg(int no) {
  this(no, null);
}
public Msg(int no, String str) {
  this(no, str);
}


对象初始化过程总结


  1. new 用到了class 文件, 所以先会找到 class文件并加载到内存


  1. 执行类的static {}代码块


  1. 在堆内存中开辟空间,分配内存地址


  1. 在堆内存中建立对象的特有属性, 并默认初始化


  1. 对属性显示初始化;


  1. 构造代码块初始化{};


  1. 构造函数初始化;


  1. 将内存地址赋给栈内存变量.


所以加载顺序中: 属性显示初始化 早于 构造代码块初始化 早于 构造函数初始化

与之类似, 静态属性显示初始化 早于 静态构造代码块初始化


代码的组织形式-使用包


在 Java 中为了防止类、接口、枚举和注释等命名冲突引用了包(package)概念,包本质上命名空间(namespace)。在包中可以定义一组相关的类型(类、接口、枚举和注释),并为它们提供访问保护和命名空间管理。


package 语句定义包,package 语句应该放在源文件的第一行,在每个源文件中只能有一个包定义语句,并且 package 语句适用于所有类型(类、接口、枚举和注释)的文件。定义包语法格式如下:package pkg1[.pkg2[.pkg3…]];


Java API简介: Java 中按包来组织类.包的组织采用分层结构,与文件系统中的目录的组织对应一致.通常将逻辑相关的类放在同一个包中。


包将类的命名空间进行有效划分,同一包中不能有两个同名的类. Java 系统提供的类库也成为Java API, 是系统提供的已实现的标准类的集合。


建立包


创建包就是在指定目录路径下创建一个子文件夹,这个包中所有类的字节码文件将存放在该文件夹下。


方法1: 创建一个 test 子目录,将源程序文件存放到该目录,在该目录下利用javac编译源代码,或者在别处编译完程序后将字节码文件拷贝到该目录即可。


方法2: 采用带路径指示的编译命令: 格式:javac –d destpath Point.java

编译器将自动在 destpath 指定的目录下建一个test子目录,并将产生的字节码文件保存到该子目录下 。典型用法是源程序放在当前目录下, 用如下命令编译 javac –d . Point.java  。编译后将在当前目录自动创建 test 子目录


包的引用


同一个包下的类之间互相引用是不需要包名的,可以直接使用。但如果类不在同一个包内,则必须要知道其所在的包。


  1. 使用类的完全限定名 :new java.util.Date()


  1. 用 import 语句加载需要使用的类。例: import java.util.Date; 然后在程序中可以直接通过类名创建对象, 如:new Date(); 用 import 语句加载整个包, 用*号代替类名位置。 它将加载包中的所有的类。例:import java.util.*;


  1. 使用静态导入,它有一个 static 关键字,可以直接导入类的公开静态方法和成员。例:import static java.util.Arrays.*;。但是注意静态导入不应过度使用,否则难以区分访问的是哪个类的代码。


封装性与访问控制


Java 面向对象的封装性是通过对成员变量和方法进行访问控制实现的,访问控制分为4个等级:私有、默认、保护和公有


image.png


Java类成员的访问控制


  • 公有级别的关键字是 public,公有级别的成员变量和方法可以在任何场合被直接访问,是最宽松的一种访问控制等级。


  • 保护级别的关键字是 protected,保护级别在同一包中完全与默认访问级别一样,但是不同包中子类能够继承父类中的 protected 变量和方法,这就是所谓的保护级别,“保护”就是保护某个类的子类都能继承该类的变量和方法。


  • 默认级别没有关键字,也就是没有访问修饰符,默认级别的成员变量和方法,可以在其所在类内部和同一个包的其他类中被直接访问,但在不同包的类中则不允许直接访问。


  • 私有级别的关键字是 private,私有级别的成员变量和方法只能在其所在类的内部自由使用,在其他的类中则不允许直接访问。


提示 访问类成员时,在能满足使用的前提下,应尽量限制类中成员的可见性,访问级别顺序是:私有级别→默认级别→保护级别→公有级别。


Jar 包


为方便使用第三方代码,也为了方便我们写的代码给其他人使用,各种程序语言大多有打包的概念,打包的一般不是源代码,而是编译后的代码。打包将多个编译后的文件打包为一个文件,方便其他程序调用。


在Java中,编译后的一个或多个包的Java class文件可以打包为一个文件,Java中打包命令为jar,打包后的文件扩展名为.jar,一般称之为jar包。


可以使用如下方式打包,首先到编译后的java class文件根目录,然后运行如下命令:

jar -cvf hello.jar <最上层包名>


程序的编译与链接


从Java 源代码到运行的程序,有编译和链接两个步骤。编译是将源代码文件变成扩展名是.class的一种字节码,这个工作一般是由 javac 命令完成的。链接是在运行时动态执行的,.class 文件不能直接运行,运行的是Java虚拟机,虚拟机听起来比较抽象,执行的就是 Java 命令,这个命令解析 .class文件,转换为机器能识别的二进制代码,然后运行。所谓链接就是根据引用到的类加载相应的字节码并执行。


Java编译和运行时,都需要以参数指定一个classpath,即类路径。类路径可以有多个,对于直接的class文件,路径是class文件的根目录;对于jar包,路径是jar包的完整名称(包括路径和jar包名)。


总结来说,import 是编译时概念,用于确定完全限定名,在运行时,只根据完全限定名寻找并加载类,编译和运行时都依赖类路径,类路径中的 jar 文件会被解压缩用于寻找和加载类。


对象销毁


对象不再使用时应该销毁。C++ 语言对象是通过 delete 语句手动释放,Java语言对象是由垃圾回收器(Garbage Collection)收集然后释放,程序员不用关心释放的细节。自动内存管理是现代计算机语言发展趋势,例如:C# 语言的垃圾回收,Objective-C 和 Swift 语言的 ARC(内存自动引用计数管理)。


垃圾回收器(Garbage Collection)的工作原理是:当一个对象的引用不存在时,认为该对象不再需要,垃圾回收器自动扫描对象的动态内存区,把没有引用的对象作为垃圾收集起来并释放。


参考



相关实践学习
消息队列+Serverless+Tablestore:实现高弹性的电商订单系统
基于消息队列以及函数计算,快速部署一个高弹性的商品订单系统,能够应对抢购场景下的高并发情况。
云安全基础课 - 访问控制概述
课程大纲 课程目标和内容介绍视频时长 访问控制概述视频时长 身份标识和认证技术视频时长 授权机制视频时长 访问控制的常见攻击视频时长
目录
相关文章
|
17天前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
14天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
37 17
|
6天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
10天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
49 4
|
21天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
42 17
|
11天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
26 2
|
15天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
19天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
19天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
20天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。