Java学习点滴——对象实例化
基于《Java编程思想》第四版
构造与析构
在C++中通过构造函数和析构函数来保证:对象在使用前被正确初始化,在使用后被正确回收。Java中同样存在构造函数,但是没有析构函数。之所以没有析构函数是因为对象实际的存储期由GC决定,程序员无法明确析构函数何时会被执行。
GC会在回收对象前执行Object的protected void finalize()方法,子类可以通过重写finalize()方法来清理资源。但是因为GC回收对象时间的不确定性,加上finalize()本身可能引入的问题,所以并不赞成使用该方法。不过Java还提供下面的格式,保证在finally里的语句必然在函数正常返回或者抛异常返回前执行,因此可以将资源的回收放在该语句块中。
try{
}finally{
}
对象初始化
在C++中,类对象实例化时,是不会初始化对象空间的,完全依靠构造函数将成员变量设置为正确的初值,但是在Java中,当得到对象的空间后会先全部清零,再开始初始化对应成员变量。
C++初始化成员变量有两种方式
- 初始化列表
- 构造函数内赋值
Java则有三种方式
- 变量定义处赋值
- 初始化语句块:分为静态初始化语句块和非静态初始化语句块,静态初始化语句块只能包含静态成员变量,非静态初始化语句块可以包含静态成员变量和非静态成员变量
- 构造函数内赋值
通过下面的代码来加深印象
class MyType{
MyType(String msg){
System.out.println(msg);
}
}
class Base{
MyType b1;
static MyType b2 = new MyType("Base static member use =");
MyType b3 = new MyType("Base non-static member use =");
MyType b4;
static MyType b5;
{
b4 = new MyType("Base non-static member in {}");
b5 = new MyType("Base static member in {}");
}
static MyType b6;
static {
b6 = new MyType("Base static member in static {}");
}
Base(){
b1 = new MyType("Base non-static member in Base()");
System.out.println("Base()");
}
}
class Derived extends Base{
MyType d1;
static MyType d2 = new MyType("Derived static member use =");
MyType d3 = new MyType("Derived non-static member use =");
MyType d4;
static MyType d5;
{
d4 = new MyType("Derived non-static member in {}");
d5 = new MyType("Derived static member in {}");
}
static MyType d6;
static {
d6 = new MyType("Derived static member in static {}");
}
Derived(){
d1 = new MyType("Derived non-static member in Derived()");
System.out.println("Derived()");
}
}
public class Main {
public static void main(String[] args) {
Derived d1 = new Derived();
System.out.println("----");
Derived d2 = new Derived();
}
}
代码的输出顺序如下,将分析也包含在输出中了
// 初始化子类时,会先初始化父类,此时先初始化静态成员变量。顺序:定义时赋值>初始化语句块。
Base static member use =
Base static member in static {}
// 父类的静态成员初始化结束后,开始初始化子类的静态成员变量。顺序:定义时赋值>初始化语句块。
Derived static member use =
Derived static member in static {}
// 以上对静态成员表初始化只在第一次加载class时执行的,后续都不会再执行了。
// 开始初始化父类的非静态成员变量。顺序:定义时赋值>初始化语句块>构造函数
Base non-static member use =
Base non-static member in {}
Base static member in {} // 此处的静态成员变量赋值会在每次类实例化对象时,执行
Base non-static member in Base()
Base()
// 开始初始化子类的非静态成员变量。顺序:定义时赋值>初始化语句块>构造函数
Derived non-static member use =
Derived non-static member in {}
Derived static member in {}
Derived non-static member in Derived()
Derived()
----
// 第二次实例化对象时,只会执行非静态成员变量的定义赋值、非静态初始化语句以及构造函数内赋值
Base non-static member use =
Base non-static member in {}
Base static member in {}
Base non-static member in Base()
Base()
Derived non-static member use =
Derived non-static member in {}
Derived static member in {}
Derived non-static member in Derived()
Derived()
总体顺序就是
- 在首次加载class时,执行静态成变量的定义赋值和静态初始化语句块内的赋值。
- 在每次实例化对象时,执行非静态成员变量的定义赋值、非静态初始化语句块内的赋值、构造函数内的赋值。
如果不实例化对象,而是直接访问静态成员变量,那么只会执行父类静态成变量的定义赋值和静态初始化语句块内的赋值
public class Main {
public static void main(String[] args) {
System.out.println( Derived.b5 );
}
}
/// 输出如下
Base static member use =
Base static member in static {}
null
因为子类可能使用到父类的东西,所以总是先初始化父类再初始化子类。同样的初始化方法和类型(static或者non-static)的成员变量的初始化顺序与其定义顺序一致。这些和C++都是一样的。加载class的细节应该是被隐藏在Java解释器里了,通过字节码看不到完整的流程,这和C++就不一样了。
Java学习点滴——对象实例化的更多相关文章
- Java学习之对象实例化
一个对象实例化过程:Person p = new Person();1,JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况下). ...
- Java学习——面对对象的思想入门
本文是看过<head first Java>之后的一点感悟,写点东西帮忙以后回忆,Java目前在我的工作中用到还不多,而我又对面对对象的编程非常的感兴趣.曾经在MFC平台上写过 ...
- Java学习点滴——初识Java
基于<Java编程思想>第四版 前言 "程序就是算法加数据结构",而算法就是控制语句加操作符,编写一个程序就是使用控制语句加操作符去操作数据结构,因此我从Java的控制 ...
- Java 学习:对象和类
对象和类 从认识的角度考虑是先有对象后有类.对象,是具体的事物.类,是抽象的,是对对象的抽象. 从代码运行角度考虑是先有类后又对象.类是对象的模板. 对象:对象是类的一个实例,有状态和行为. 类:类是 ...
- Java学习点滴——Integer缓存
前言 一切从下面这段代码开始 public static void test(String[] agrs){ Integer a = 1; Integer b = 2; System.out.prin ...
- Java学习点滴——泛型
基于<Java编程思想>第四版 前言 虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的. 语法 Java只需要一个<>就可定义泛型.在<> ...
- Java学习点滴——Class和反射
基于<Java编程思想>第四版 前言 我们要操作一个类实例对象时,一般都要先知道这个类有哪些方法或者成员变量.反射就是在我们不知道这个类有哪些方法或成员变量时,使用特定方式得到类的这些信息 ...
- Java学习笔记--对象克隆
转自:Edward_qing_Lee 的专栏 http://blog.csdn.net/edward_qing_lee/article/details/8249102 一.java 方法参数 理解: ...
- JAVA学习一 对象数组
对象数组 今天在写一个代码,才发现自己对于对象数组的理解是不够的,那么就讲讲自己现在的理解. 对于数组中的每一个元素都是一个针对对象的引用 他会指向你的具体的一个堆上的对象,它本身知识一个地址值,与其 ...
随机推荐
- Python的re模块
什么是re模块,re模块有什么作用? re模块是Python提供的一个正则表达式相关的模块,主要是针对字符串进行模糊匹配,所以在字符串匹配这一功能上,re相当专业. 什么是模糊匹配? 之前的学习字符串 ...
- 视频当道的时代,这些珍藏的优质 Python 播客值得推荐
我国互联网的发展道路与欧美不同,在内容的形式上,我们似乎实现了跨越式的发展——早早进入了移动互联网时代,直播和短视频等形式的内容成为了潮流,而文字形式的博客(blog)与声音形式的播客(podcast ...
- [JavaScript] AMD和CMD概述
1. cmd 和 amd 在浏览器中,受网络和浏览器渲染的制约,不能采用同步加载,只能采用异步加载.于是 AMD 规范应运而生 2. AMD AMD(Asynchronous Module Defin ...
- 模块使用:time、datetime、calendar、sys、os、os.path、normcase和normapath、random、json、pickle
## time:时间 时间戳(timestamp):time.time() 延迟线程的运行:time.sleep(secs) (指定时间戳下的)当前时区时间:time.localtime([secs] ...
- 程序员如何巧用Excel提高工作效率
作为一名程序员,我们可能很少使用Excel,但是公司的一些职能部门,比如HR,财务等,使用Excel真的是太熟练了,以至于一些系统开发出来,导入和导出功能是使用最频繁的,哈哈. 其实在程序开发的过程中 ...
- Vue.js 学习笔记 第5章 内置指令
本篇目录: 5.1 基本指令 5.2 条件渲染指令 5.3 列表渲染指令 v-for 5.4 方法与事件 5.5 实战:利用计算属性.指令等知识开发购物车 回顾一下第2.2节,我们己经介绍过指令(Di ...
- ArcGIS JavaScript API4.8 底图选择的几种方案
创建一个HTML页面,引入ArcGIS JavaScript API,在<body>标签内创建一个div并添加ID值,在<head>标签内设置样式<style>,在 ...
- SQL Server的Descending Indexes
SQL Server的Descending Indexes 测试环境:SQL Server 2012 表结构如下 USE [test] GO CREATE TABLE [dbo].[tt8]( ,) ...
- LDAP客户端在Windows环境的部署及配置
ldap客户端配置安装目录的子目录C:\OpenLDAP\etc\openldap,编辑slapd.conf,修改密码,保存并关闭文件.rootdn "cn=Manage ...
- Win7系统修改hosts无法保存怎么办?
背景 有的时候我们需要修改hosts文件,但是在某些情况下竟提示保存不了.之前有一次IntelliJ IDEA提示我快到期了,于是我到网上找到了一个激活方法,但需要将一个地址放到hosts文件中去,此 ...