软件构造——Java 学习记录

本文深入探讨了Java的基础知识,包括标识符命名规则、注释类型、变量理解以及面向对象编程的核心概念。详细阐述了类的构造方法、继承与多态,并介绍了抽象类、接口以及包的作用。此外,还触及了Java泛型的基本应用,帮助读者更好地理解和运用Java语言。

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

本文为 Java 的学习记录。本文内容参考了廖雪峰的 Java 教程以及菜鸟教程的 Java 教程

Java 介于编译型语言和解释型语言之间。Java 将代码编译成 Java 字节码,它类似于抽象的 CPU 指令。然后,针对不同的平台编写 Java 虚拟机,不同平台的虚拟机负责加载字节码并执行,这样就实现了“一次编写,到处运行”的效果。

本文将不着重介绍 Java 的基本使用语法,而是关注在此基础上的使用原则。

Java 基础

标识符命名规则

Java 是一个面向对象的程序设计语言,它的一个基本单位就是类,关键字为 class。对于一个类,我们有着如下的命名原则:

  • 以大写英文字母开头,采用采用大驼峰命名法。

大驼峰命名法是当标识符由一个或多个单词连结在一起来构成时,每个单词的首字母都大写,其余字母小写。每个单词之间紧密相连。

对于类中的方法或属性、变量,有如下的命名原则:

  • 以小写字母开头,采用小驼峰命名法。

小驼峰命名法就是将大驼峰的第一个单词大写的首字母变为小写,其余的单词不变。

注释

Java 中有三种类型的注释。

第一种是单行注释,以双斜线开头,直到这一行的结尾结束:

// 这是单行注释

第二种是多行注释,以 /* 开头,以 */ 结束,可以有多行:

/*
这是
多行
注释
*/

第三种是一种特殊的多行注释,以 /** 开头,以 */ 结束,如果有多行,每行以 * 开头:

/**
 * 可以用来自动创建文档的注释
 *
 * @param whatever...
 */

这种特殊的多行注释需要写在类和方法的定义处,可以用于自动创建文档。

对 Java 变量的理解

事实上,我们不能用理解 C 和 C++ 中理解变量的方式来理解 Java 中的变量。在 Java 中,变量名更像是一种标签,它贴在变量实际存储在的内存上。而如果我们理解成变量名是一种“容器”,用来存放一个值的话,那么就会遇到很多令人费解的问题。如果用 C 或 C++ 的角度来解释它,这个变量名就像是一种指针,只不过你每次使用它都默认当作取它的引用。理解这一点非常重要,这会使你能够理解 Java 变量的一些可能导致你迷惑的性质。

那么当你为 Java 中的一个变量赋值的时候,Java 究竟是怎么做的呢?

假设一个变量 a,它原来的值是 1,这意味着在内存中有一个位置存储着值 1,而 a 记住了这个位置,当你使用 a 的值的时候,它就去这个地址取这个值。当你又试图给 a 赋值的时候,Java 在内存中又新创建了一个值(也就是等于你要赋的那个值),放在另一个位置,a 抛弃了之前记住的那个地址,而去记住这个新的内存位置。至于之前那个位置的值怎么样了,一般来说,如果那个位置没有同时被其他变量记住的话,那就交给 Java 的垃圾回收机制处理了。

这种理解方式对于 Java 引用类型的变量尤其合适。我们知道,使用 Java 必须和大量的引用类型的变量打交道。举个例子:字符串、数组、库中的类还有你自己写的类,与其对应的都是引用类型的变量。无论可变类型的变量还是不可变类型的,都适用这种理解方式。

Java 面向对象编程

面向对象编程以对象为核心,该方法认为程序由一系列对象组成。类是对现实世界的抽象,包括表示静态属性的数据和对数据的操作,对象是类的实例化。对象间通过消息传递相互通信,来模拟现实世界中不同实体间的联系。在面向对象的程序设计中,对象是组成程序的基本模块。

我们要注意:一个 Java 源文件可以包含多个类的定义,但只能定义一个 public 类,且 public 类名必须与文件名一致。如果要定义多个 public 类,则必须拆到多个 Java 源文件中。

类的构造方法

在我们创建类的实例的时候,实际上是通过构造方法来初始化实例的,构造方法只会在对象被创建的时候调用。构造方法的名称就是类名,构造方法的参数没有限制,在方法内部,也可以编写任意语句。但是,构造方法没有返回值(连 void 也没有)

每个类都有构造方法。如果一个类没有定义构造方法,那么编译器会自动生成一个默认构造方法,它没有参数,也没有执行语句。需要注意的是,如果我们定义了一个构造方法,那么,编译器就不再自动创建默认构造方法。

一个类的构造方法,也不是唯一的。它可以通过**重载(overload)**的方法来定义多个构造方法。这些构造方法的名字都是一样的,区别在于参数(如参数的数量、位置、类型)不同。

类的继承与多态

类的继承带来的一个重要优势就在于提高了代码的复用性。子类自动获得了父类的字段和方法注意,正因如此,子类中严禁定义与父类同名的字段,而如果定义与父类相同的方法(注意,要求方法名相同、参数相同、返回值类型相同)则会重写(override)这个方法。如果只是方法名相同,则是会重载这个方法。

另外需要注意的是:子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。

如果子类重写了父类的方法,那么实际运行(可能在代码中,我们不能确定此时的对象究竟是父类还是子类的实例)时,究竟调用谁的方法呢?Java 对象的方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。这个非常重要的特性在面向对象编程中称之为多态(polymorphic)。多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。

在 Java 中,所有类(除 Object 类外)都直接或间接继承自 Object 类,而 Object 类也定义了一些方法,其中几个如下:

  • toString():把对象输出为 String
  • equals():判断两个对象是否逻辑相等;
  • hashCode():计算一个对象的哈希值。

这也意味着我们可以重写 Object 类的这些方法,来使得这些方法也对我们设计的类正确处理。

抽象类与接口

通过 abstract 关键字可以将一个方法声明为抽象方法,抽象方法没有任何的实现语句。含有抽象方法的类就是抽象类。抽象类无法实例化,因为它的抽象方法并没有实现出来。抽象类它的存在意义就是为了被继承,它要强迫继承它的子类实现它的抽象方法。

抽象类直接体现了多态的概念,引用抽象类,我们只需要对其进行方法调用,而不需要关心它的具体子类型。

在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现,这样,多态就能发挥出威力。那个,如果一个抽象类没有字段,所有方法全部都是抽象方法,我们就可以把该抽象类改写为接口。

接口定义的所有方法默认都是 public abstract 的,所以这两个修饰符不需要写出来(写不写效果都一样)。

我们需要注意,在 Java 中,一个类只能继承自另一个类,不能从多个类继承。但是,一个类可以实现多个接口。

Java 引入包(package),主要是为了解决命名冲突。Java 定义了一种名字空间,称之为包。一个类总是属于某个包,类名只是一个简写,真正的完整类名是包名.类名。如果一个源文件中没有使用包声明,那么它将被安排到默认包中。通常使用小写的字母命名包,来避免与类、接口名字的冲突。

包可以是多层结构,用 . 隔开。Java 文件对应的目录层次要和包的层次一致。需要注意的是:包没有父子关系。java.utiljava.util.zip 是不同的包,两者没有任何继承关系。

我们在使用编译器编译时,默认自动导入了 java.lang 包,这就是我们之前没有手动引入任何包却不报错的原因。

Java 泛型

泛型就是编写模板代码来适应任意类型。我们可以通过改变泛型参数 <T> 中的 T 为某个特定的引用类型来使用泛型。可以为类、接口、方法编写泛型。

例如,我们可以按照如下的方式定义一个泛型的类:

public class MyClass<T> {
    ...
}

这样,T 就可以作为一种类型在类内部使用,而 T 真正的类型取决于实例化这个类时在 <> 中填写的类型。泛型还可以有多种类型,参数间用逗号隔开。比如,如果我们想要使用两种类型,可以写成:

public class MyClass<T, K> {
    ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值