开始Thinking in java系列,这一章以对象和引用为核心,对JAVA语言进行了基础性地解释。该系列博客会大致根据本书原有目录对其内容进行总结概括并尽可能诠释清楚其核心知识点。
JAVA语言面向对象编程,整个体系都可由对象和引用两部分组成。那么,什么是对象呢?什么又是引用?
首先看到这样两条语句:
String s = new String(“abc”);
ATypeName a = new ATypeName();//ATypeName 是一个类名
上述语句就是定义一个字符串变量以及实例化一个对象
不管是在JAVA中还是C语言中,我们想要使用一份数据或是进行一项行为操作,都必须要进行定义,定义变量或是实例化对象(对已有的类进行对象定义)。在上述举例中,String s中的s就是一个被创建的引用,而“=”另一边的new内容才是创建一个对象;同样地,对于实例化对象来说,a也仅仅是一个引用,只有new后(可以不使用new,如==String s = “abc”;==也是正确的方式但二者有区别)才算是创建了对象。
我们知道,定义变量或实例化方法都需要给其对象分配内存空间,在JAVA中,所有的对象都被存储在堆中,在上述语句中,如果不进行new操作而仅仅==String s;==的话,实质上变量s本身并没有可以引用的对象的,这样一来,在运行时因为没有引用对象的缘故编译器就会报错。
基本类型 | 大小 | 包装器类型 |
---|---|---|
boolean | - | Boolean |
char | 16-bits | Character |
byte | 8-bits | Byte |
short | 16-bits | Short |
int | 32-bits | Integer |
long | 64-bits | Long |
float | 32-bits | Float |
double | 64-bits | Double |
void | - | Void |
上一小节中说到如果不进行new初始化,变量s的定义在运行时会报错,其实还有一类特殊情形,当在类中时(所有代码内容都必须在类中,但是类中又可以定义方法,方法中的变量称作局部变量不在此情形范围内),这些基础类型所定义变量可以不用进行初始化而拥有默认值,这种情形下编译器是不会报错的。而且这类变量不使用new进行初始化也并非是一个引用,而是直接赋值并存储于堆栈中。而包装器类型则需要new初始化,和其它类型数据一样定义。
所有上述数值类型都有正负号,而不是无符号。
boolean类型没有明确空间大小。仅能定义为true或false两种取值。
还有两类用于高精度计算的类:BigInteger和BigDecimal,二者大体属于包装器类的范畴但没有具体对应的基本类型,这两个类包含的方法操作和Int、float相同,并且其分别支持任何精度的整数和定点数。
{
int x = 12;
{
int y = 24;
}
}
在这样一段代码中,变量x和y分别只能在自己所定义的花括号中使用,花括号结束时这两个变量就不可再进行调用,而由new创建的对象还可以保留下去,直到被java的垃圾回收器自动辨别回收。这样做就消除了内存泄漏的问题。
在JAVA中,既然一切都是对象,那么是什么决定了某一类对象的外观和行为呢?是class类。
关键字class用来创建一个类,如:
class ATypeName { /* Class body */
int i;//此处有默认值,不会报错
}
ATypeName a = new ATypeName();
a.i = 10;
ATypeName b = new ATypeName();
b.i = 5;
这就是最开始时我们实例化对象进行的操作,ATypeName是一个类名,用class关键字创建类ATypeName,花括号中内容为类体,其中可定义成员变量(又称字段)和成员方法,用以实现外观和行为。一个类相当于一个模板,实例化就是对照这个模板复刻一个真正的对象。但在实例化对象之前,我们只创建了类ATypeName,除了之后会提到的static静态变量和静态方法之外的所有成员变量以及成员方法,都还没有分配存储空间。或者说,每实例化一个新的对象(可以实例化多个对象),在new初始化之后才会给这个对象应有的成员变量以及成员方法分配空间存入堆中。
a和b是两个不同的实例化对象(实质上就是之前提到的两个不同对象的引用,不要被名称搞混)它们的内容是单独存放在属于自己的区域的。
而创建对象之后引用类中的成员变量或成员方法时,就需要在实例化对象名称后添加句点**.**,再接原类中成员变量或成员方法的名称。而且根据实例化原则,a也算是一个新的变量,只是这个变量的类型是一个类,如果a也在一个类中属于成员变量,那么这个类在实例化对象的时候要想引用a.i只需要将a.i看做整体放在新的对象名称句点之后。
上面我们说到一个类拥有两种数据元素,一个是成员变量,上面已经具体讲解了。而另一种,就是成员方法。JAVA中的方法在C语言中被称作函数,都是具体行为。
假设有一个方法f(),不带任何参数,返回类型是int。如果有一个名为a的对象,则可以通过它调用f(),写法如下:
int x = a.f();
返回值类型必须要于x的类型兼容(即容量可大不可小且同为整型或浮点型)。
这种调用方法的行为通常被称作发送消息给对象,在上述中,消息是f(),对象是a。
一个方法通过什么来确定它的独立性呢?或许我们能想到是名称,但是一定要注意,JAVA中的方法通过方法名和参数列表唯一地标识出某个方法。
一个类至少拥有一个构造方法,构造方法必须与类名相同,多个构造方法之间通过参数列表进行区分,即调用一个构造方法时编译器会自动根据你传入的参数类型以及数量为你选择相应的构造方法,如果没有自定义构造方法,编译器会自动为该类提供一个默认的构造方法。
刚刚我们知道了每一个对象都有自己独立的存储空间,并且其数据内容只有在实例化之后才会进行分配空间。那么,如果我们需要使用的数据元素不需要实例化对象怎么办?
这种情况下就要使用static关键字,它能够为类创建一个静态变量或者静态方法,这一类数据元素在类定义完之后就会被分配空间,那么即使没有创建实例化对象也可以通过类名.变量名或类名.方法名来直接调用静态变量或静态方法,有实例化对象之后也可以通过对象名.变量名进行调用,但为了区别并不推荐。而且一个类所有的静态方法和静态变量都是独一份的,这意味着不管创建多少个实例化对象,所有的静态方法和静态变量都是共享的。所以面对static变量和方法一定要注意。
当我们在一个类中创建一个成员变量用来引用另一个类的时候,如果这两个类并不在同一个文件中时,必须要使用import语句在文件开头部分导入另一个类才能继续使用,否则编译器会因不清楚这个实例化对象的模板在哪而报错。其中,特定类java.lang不需要人为导入,每一个程序文件会自动导入这个类。
使用格式如下:
import java.util.*;//*表示该目录下所有类,.用来分开上下两个目录,最后一个是类文件名;
具体IDEA配置javadoc文档参考:https://www.cnblogs.com/cyberniuniu/p/5021910.html
具体javadoc核心内容参考:
https://blog.csdn.net/vbirdbest/article/details/80296136