3.1 类的基本概念
- 函数的容器
- 自定义的数据类型
3.1.1 函数容器
- 类方法
- 实例方法
- 通过private封装和隐藏内部实现细节,避免被误操作,是计算机程序的一种基本思维方式
3.1.2 自定义的数据类型
- 类变量
- 类型本身具有的属性
- static修饰符是必须的
- 类方法
- 实例变量
- 实例方法
3.1.3 定义第一个类
public class Point {
public int x;
public int y;
public double distance() {
return Math.sqrt(x*x + y*y);
}
}
-
类方法vs实例方法
- 类方法只能访问类变量,不能访问实例变量
- 类方法只能调用类方法,不能调用实例方法
- 实例方法既可以访问类变量,也能访问实例变量
- 实例方法既可以调用类方法,也能调用实例方法
3.1.4 使用第一个类
public static void main(String[] args) {
Point p = new Point();
p.x = 2;
p.y = 3;
System.out.println(p.distance());
}
- 声明变量本身只会分配存放位置的内存空间,这块空间还没有指向任何实际内容。
- 引用类型:不存储数据,只是存储实际内容的位置
- 在创建对象的时候,所有的实例变量都会分配一个默认值
- 数值类型变量:0
- boolean:false
- char:”\u0000”
- 引用变量:null
- 面向对象思维:通过对象来访问和操作其内部的数据
3.1.5 变量默认值
- 实例变量:
- 定义变量的时候赋值
- 初始化代码块中赋值
- 在新建一个对象的时候,会先调用{}里面的初始化代码,然后才会执行构造方法中的代码
int x = 1; int y; { y = 2; }
-
类变量
static int STATIC_ONE = 1; static int STATIC_TWO; static { STATIC = 2; }
- 静态初始化代码块:static{}。
- 静态初始化代码块在类加载的时候执行,在创建对象之前,且只执行一次
3.1.6 private变量
public class Point {
private int x;
private int y;
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public double distance() {
return Math.sqrt(x * x + y * y);
}
}
- this表示当前实例
- 一般不将成员变量定义为public
3.1.7 构造方法
public Point() {
this(0, 0);
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
- 名称是固定的,与类名相同
- 没有返回值,也不能有返回值。构造方法隐含的返回值就是实例本身。
- this(0, 0)
- 用于在构造方法中调用其他构造方法
- this必须放在第一行?
Point p = new Point(2, 3);
- 分配内存
- 给实例变量设置默认值
- 调用构造方法
- 默认构造方法
- 如果没有定义构造方法,编译器会自动生成一个默认构造方法
- 一旦定义了构造方法,编译器就不会再生成默认的
- 私有构造方法
- 不能创建实例的类,类只能被静态访:Math、Arrays类
- 能创建实例的类,但只能被类的静态方法调用:单例
- 只是用来被其他多个构造方法调用,用于减少重复代码
3.1.8 类和对象的生命周期
- 当第一次通过new创建一个类的对象时,或者直接通过类名访问类的变量和方法时,Java会将类加载进内存,为这个类分配一块空间
- 类加载进内存之后,一般不会释放,直到程序结束
- 一般情况,类只会加载一次,所以静态变量在内存中只会有一份
- 每new一次,就会产生一个对象,就会有一份独立的实例变量值
- 实例对象中会存储对应类的地址,这样通过对象也能访问到类的变量和方法
- 实例方法可以理解成静态方法,只是多了一个参数this
- 对象的释放是用垃圾回收机制管理的
- 栈的内存是自动管理的,堆的内存是用垃圾回收机制管理的
3.1.9 小结
通过类实现自定义数据类型,封装该类型的数据所具有的属性和操作,隐藏实现细节,从而在更高的层次上考虑和操作数据,是计算机程序解决复杂问题的一种重要的思维方式。
3.2 类的组合
- 分解现实问题中涉及的概念及概念间的关系,将概念表示为多个类,通过类之间的组合来表达更为复杂的概念以及概念间的关系,是计算机程序的一种基本思维方式
- 道生一、一生二、二生三、三生万物
- 二进制表示和运算看做一
- 基本数据类型看做二
- 基本数据类型组成的类看做三
- 类的组合及继承使得三生万物
3.3 代码的组织机制
3.3.1 包的概念
- 命名冲突
- 完全限定名 java.lang.String
-
声明类所在的包
- package
-
通过包使用类
- 通过类的完全限定名
- 将用到的类引入当前类
- import
- import java.util.*,只会引入java.util包下的直接类,而不会引入包下嵌套的类,比如java.util.zip,试图嵌套引入的形式也是无效的,比如import java.util.*.*
- Eclipse中 Ctrl+Shift+O自动管理引用的类
- import
- 静态导入 import static 导入类中的public静态方法
-
包的可见范围
- 对于类、变量和方法,什么修饰符都不写,默认可见范围是同一个包。同一个包指的是直接包,子包下的类并不能访问。
- protected可见性包括包可见性
- private < 默认(包)< protected < public
3.3.2 jar包
编译后的一个或多个包的Java class文件可以打包为一个文件,Java中打包命令为jar,打包后的文件扩展名为.jar,一般称之为jar包
jar -cvf <包名>.jar <最上层包名>最上层包名>包名>
3.3.3 程序的编译与链接
- 编译是将源代码文件变成扩展名是.class的一种字节码
- 链接是根据引用到的类加载相应的字节码并执行
- Java编译和运行时,都需要以参数指定一个classpath,即类路径。
- import是编译时概念,用于确定完全限定名,在运行时,只根据完全限定名寻找并加载类。编译和运行时都依赖类路径,类路径中的jar文件会被解压缩用于寻找加载类。
3.3.4 总结
- 将类和接口放在合适的具有层次结构的包内,避免命名冲突,代码可以更为清晰,便于实现封装和模块化开发
- 通过jar包使用第三方代码,将自身打包为jar包供其他程序使用
- Java 9中引入了模块的概念。
- 一个应用由多个模块组成,一个模块可由多个包组成
- 模块之间可以有依赖关系,一个模块可以导出给包给其他模块使用,也可以使用其他模块提供的包
- 更强的封装,更可靠的配置、更为松散的耦合、更动态灵活。