Java是一种面向对象的编程语言,它将世界视为具有属性和行为的对象的集合。 Java的面向对象版本非常简单,它是该语言几乎所有内容的基础。 因为它对Java非常重要,所以我将对幕后内容进行一些解释,以帮助任何不熟悉Java的人。
遗产
通常,所有笛卡尔几何对象 (例如圆形,正方形,三角形,直线和点)都具有基本属性,例如位置和延伸。 具有零扩展的对象(例如点)通常没有其他东西。 像线这样的对象具有更多的对象,例如,线段的起点和终点,或沿线的两个点(如果是“真线”)。 诸如正方形或三角形之类的对象还有更多的东西(例如,拐角点),而圆形可能具有中心和半径。
我们可以看到这里有一个简单的层次结构:通用几何对象可以扩展为特定的几何对象,例如点,线,正方形等。每个特定的几何对象都继承了位置和扩展的基本几何属性,并添加了自己的属性属性。
这是单继承的示例。 Java最初的面向对象模型仅允许单一继承,其中对象不能属于多个继承层次。 该设计决策来自于程序员在复杂的多重继承场景中面临的种种歧义,通常是在“有趣的设计决策”导致在定义(和重新定义)函数foo()的几种可能实现的情况下层次结构。
从Java 8开始,就已经存在有限的多重继承结构,该结构要求代表程序员采取特定的措施以确保不存在歧义。
强而静态的打字
Java是强类型和静态类型。 这是什么意思?
静态类型语言是一种在编译时就知道变量类型的语言。
在这种情况下,不可能将B类型的值分配给声明类型为A的变量,除非存在一种将B类型的值转换为A类型的值的转换机制。转换将整数值(例如1、2或42)转换为浮点值(例如1.0、2.0或42.0)。
强类型语言是一种自动应用很少(或可能没有)类型转换的语言。 例如,强类型语言可能允许将整数自动转换为实数 ,但绝不会允许将实 数自动转换为实 数,因为在一般情况下,该转换需要舍入或截断。
基本类型,类和对象
Java提供了许多原始类型: 字节 (八位带符号整数); 短 (16位有符号整数); int (32位有符号整数); long (64位有符号整数); float (单精度32位IEEE浮点数); double (双精度64位IEEE浮点数); 布尔值 (对或错); 和char (16位Unicode字符)。
除了这些原始类型,Java还允许程序员使用类声明创建新类型。 类声明用于定义对象模板,包括其属性和行为。 声明一个类后,通常可以使用new关键字创建该类的实例 。 这些实例直接对应于我们一直在讨论的“对象”。 Java附带了一个有用的类定义库,其中包括一些简单的基本类,例如String ,它用于保存诸如“ Hello,world”之类的字符序列。
让我们定义一个简单的消息类,其中包含发件人的名称以及消息文本:
class Message
{
String sender
;
String text
;
public Message
(
String sender,
String text
)
{
this .
sender
= sender
;
this .
text
= text
;
}
}
该类声明中有几件重要的事情要注意:
- 按照惯例,该类始终以大写大写字母声明。
- Message类包含两个属性(或字段):
–一个名为sender的String字段
–一个名为text的字符串字段
属性或字段(按惯例)始终以小写前导字母声明。 - 从公共消息开始就有某种东西。
–这是一种方法 (方法定义对象的行为)。
–用于构造 Message类的实例。
–构造方法始终与类具有相同的名称,并应理解为构造后便返回该类的实例。
–其他方法(按照惯例)始终以小写字母开头。
–此构造函数是“公共的”,表示任何调用者都可以访问它。 - 作为构建过程的一部分,一些行从此开始。
– 这是指该类的当前实例。
–因此, this.sender引用对象的sender属性。
–而普通发件人是指消息构造函数方法的参数。
–因此,这两行将对构造函数的调用中提供的值复制到对象本身的字段中。
因此,我们有了Method类的定义。 我们如何使用它? 以下代码摘录显示了一种可能的方法:
Message message = new Message ( "system" , "I/O error" ) ;
Message message = new Message ( "system" , "I/O error" ) ;
在这里我们看到:
- 类型信息的可变信息的声明
- 创建消息类的新实例,并将发送者设置为“系统”,并将文本设置为“ I / O错误”
- 将Message的新实例分配给可变message
- 如果在代码的后面部分,为变量message分配了一个不同的值( Message的另一个实例),并且没有创建任何其他引用此Message实例的变量,则该实例将不再被任何人使用,并且可以被垃圾回收。
这里发生的关键是我们正在创建Message类型的对象,并在变量message中保留对该对象的引用。
我们现在可以使用该消息; 例如,我们可以在sender和text属性中打印值,如下所示:
System .
out .
println
(
"message sender = "
+ message.
sender
)
;
System .
out .
println
(
"message text = "
+ message.
text
)
;
这是一个非常简单且不复杂的类定义。 我们可以通过多种方式修改此类的定义:
- 通过在声明前使用关键字private ,可以使调用者看不到属性的实现细节,从而使我们可以在不影响调用者的情况下更改实现。
- 如果我们选择隐藏类中的属性,则通常将定义获取和设置这些属性的过程。 按照Java中的约定,这些定义为:
– 公共字符串getSender()
– 公共字符串getText()
– 公共无效setSender(字符串发送方)
– 公共无效setText(字符串文本) - 在某些情况下,我们可能希望具有“只读”属性; 在这种情况下,我们不会为此类属性定义setter。
- 通过使用private关键字而不是public,可以使调用者看不到该类的构造函数。 当我们有另一个类负责创建和管理消息池(可能在另一个进程甚至在另一个系统中执行)时,我们可能希望这样做。
现在,假设我们想要一种消息,该消息记录何时生成。 我们可以这样声明:
class TimedMessage
extends Message
{
long creationTime
;
public TimedMessage
(
String sender,
String text
)
{
super
( sender, text
)
;
this .
creationTime
=
System .
currentTimeMillis
(
)
;
}
}
在这里,我们看到了一些新东西:
- TimedMessage 扩展了Message类-也就是说, TimedMessage正在继承Message的属性和行为。
- 构造函数在其父类或父类中调用构造函数,并将sender和text的值作为super(sender,text)传入,以确保正确继承其继承的属性。
- TimedMessage添加了一个新属性creationTime ,并且构造函数将其设置为当前系统时间(以毫秒为单位)。
- 在Java中,以毫秒为单位的时间保持为一个长(64位)值(0为1970年1月1日00:00:00 UTC)。
- 顺便说一句,名称creationTime暗示它应该是一个只读属性,这也暗示其他属性是只读的。 也就是说, TimedMessage实例可能不应重用,也不应更改其属性。
对象类
从术语上讲,“对象类”听起来像是一种矛盾,不是吗? 但是请注意,我们定义的第一个类Message 似乎并没有扩展任何东西,但实际上可以扩展。 所有没有专门扩展另一个类的类都将Object类作为其直接父类和唯一父类。 因此,所有类都将Object类作为其最终超类。
您可以在Java文档中了解有关Object类的更多信息 。 让我们(简要地)回顾一些有趣的细节:
- Object具有构造函数Object() ,即没有参数。
- 对象为其所有子类提供了一些有用的方法,包括:
– clone() ,它创建并返回当前实例的副本
– equals(Object anotherObject) ,它确定anotherObject是否等于当前的Object实例。
– finalize() ,用于在不再使用实例时对其进行垃圾回收(请参见上文)
– getClass() ,该类返回用于声明手头实例的类
—由此返回的值是Class类的实例, 该类允许在运行时学习声明类(称为introspection的过程)。 - hashCode()是一个整数值,它为当前实例提供了几乎唯一的值。
–如果两个不同实例的哈希码相等,则它们可以相等; 为了确定完全相等,必须对属性(可能还有方法)进行详细比较;
–如果哈希码不相等,则实例也不相等。
–因此,哈希码可以加快相等性测试的速度。
–哈希码也可以用于创建HashMap (映射是使用哈希码加快查找速度的关联数组或字典)和HashSet (集合是对象的集合;程序员可以测试实例是否是否在集合中;使用哈希码来加快测试速度)。 - notify() , notifyAll() , wait() , wait(long timeout)和wait(long timeout,int nanos)在单独线程上执行的协作实例之间进行通信。
- toString()生成实例的可打印版本。
结论性思想
我们已经谈到了Java风格的面向对象编程的一些重要方面。 在以后的文章中将涉及六个重要的相关主题:
- 命名空间和包
- 子类中的重写方法-例如,String类具有自己的特定hashCode()方法,该方法将其含义识别为字符数组; 这是通过重写从Object继承的hashCode()方法来完成的
- 接口,允许描述必须由实现该接口的类提供的行为; 当唯一感兴趣的是特定行为时,可以通过该接口引用实现给定接口的类的实例
- 原语或类的数组以及类的集合(例如列表,映射和集合)
- 方法的重载-具有相同名称和相似行为的几种方法具有不同的参数
- 使用Java发行版随附的库
接下来您想阅读什么吗? 让我们在评论中知道并继续关注!