【Java】初始化
默认域初始化
- 如果在构造器中没有显示地给域赋予初值,那么就会被自动赋予默认值:数值为0,布尔值为false,对象引用为null。
无参数构造器
很多类都包含一个无参数的构造函数,对象由无参数构造函数创建时,其状态会设置为适当的默认值。例如,如下是Employee的无参数构造函数:
pubilc Employee() {
name = "";
salary = 0;
hireDay = new Date();
}
- 如果编写一个类时没有编写构造器, 那么系统就会提供一个无参数的构造器。这个构造器将所有的实例域设置为默认值。于是,实例域中的数值型数据设置为0、布尔型数据设置为false,所有对象引用将设置为null。
- 如果类中至少提供了一个构造器,但是没有提供无参数的构造器,则在构造对象如果没有提供参数就会被视为不合法。
显示域初始化(指定初始化)
由于类的构造器方法可以重载,所以可以采用多种形式设置类的实例域的初始状态。确保不管怎么调用构造器,每个实例域都可以被设置为一个有意义的数初值。这是一种很好的设计习惯。
可以在类的定义中,直接将一个值付给任何域。例如:
class A{}
Class Employee {
private String name = "";
private A a = new A();
}
在执行构造器之前先执行赋值操作。当一个类的所有构造器都希望把相同的值赋给某个特定的实例域时,这种方式特别有用。
初始值不一定是常量。在下面这个例子中,可以调用方法对域进行初始化。Employee类中每个雇员都有一个id域。可以使用下列方式进行初始化:
class Employee{
private static int nextId;
private int id = assignId();
private static int assignId() {
int r = nextId();
nextId++;
return r;
}
}
这个方法也可带有参数,但这些参数必须是已经初始化的了。因此,可以这样写:
public class MethodInit {
int i = f();
int j = g(i);
int f() {return 11;}
int g(int n ) {return n* 10;}
但像下面这样就不对了:
public class MethodInit{
int j = g(i); //Illegal forward reference
int i = f();
int f() {return 11;}
int g(int n) {return n * 1
初始化块
前面已经讲过两种初始化数据域的方法:
- 在构造器中设置值
- 在声明中初始化
实际上,Java中还有第三种机制,称为初始化块。在一个类的生命中,可以包含多个代码块。只要构造类的对象,这些块就会被执行。例如:
class Employee{
private static int nextId;
private int id;
private String name;
private double salary;
//object initialization block
{
id = nextId;
nextId++;
}
public Employee(String n, dobule s) {
name = n;
salary = s;
}
public Employee(){
name = "";
salary = 0;
}
}
在这个示例中,无论使用哪个构造器构造对象,id域都在对象初始化块中被初始化。首先运行初始化块,然后才运行构造器的主体部分。
this关键词
假设你希望在方法的内部获得对当前对象的引用,就可以使用this关键字。this关键字只能在方法的内部使用,表示对“调用这个方法的那个对象”的引用。this的用法和其他对应引用并无不同。只要注意,如果在方法内部调用同一个类的另一个方法,就不必使用this,直接调用即可。
只有当需要明确指出对当前对象的引用时,才需要使用this关键字。例如,当需要返回对当前对象的引用时,就常常需要在return语句里这样写:
public class Leaf{
int i = 0;
Leaf increment() {
i++:
return this;
}
}
public static void main(String[] args) {
Leaf x = new Leaf();
x.increment().increment().increment();
}
由于increment()通过this关键字返回了对当前对象的引用,所以很容易在一条语句中对同一个对象进行多次操作。
this关键字对于将对于将当前对象传递给其他对象也很有用:
Class Person{
public void eat(Apple apple) {
Apple peeled = apple.getPeeled();
System.out.println("Yummy");
}
}
class Peeler {
static Apple peel(Apple apple) {
//... remove peel
return apple; //Peeled
}
}
class Apple{
Apple getPeeled() {return Peeler.peel(this);}
}
public class PassingThis {
public static void main(Strings[] args) {
new Person.eat(new Apple));
}
}
参数名
构造器的的参数名和引用如下所示:
Class Employee{
private String name;
private double salary;
public Employee(String name , double salary) {
this.name = name;
this.salary = salary;
}
}
它基于这样一个事实:参数变量用同样的名字将实例域屏蔽起来。例如,如果将参数命名为salary,salary将引用这个参数,而不是实例域。但是,可以采用this的形式访问实例域。
调用另一个构造器
如果构造器的第一个句子形如(this...),这个构造器将调用同一个类的另一个构造器。下面是一个典型的例子:
public Employee() {
//calls Employee(String, double)
this("Employee #" + nextId, s);
nextId++;
}
尽管可以用this调用另一个构造器,但却不能同时调用两个。此外,必须将构造器调用置于方法最起始处,否则编译器会报警。
静态域初始化
- 如果一个域是静态的基本类型域,且没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始值就是null。
- 如果想在定义处进行初始化,采取的方法与非静态数据没什么不同
Class A{
private static B b = new B();
}
3.也可以用使用指定初始化,不过要在初始化块的外面加 static关键字
class Cup{
Cup(int marker) {
}
}
class Cups{
static Cup cup1;
static Cup cup2;
static {
cup1 = new Cup(1);
cup2 = new Cup(2);
}
Cup() {
print("Cups()");
}
}
public class ExplicitStatic {
public static void main(Strings[] args) {
print("Inside main()");
Cups.cup1.f(99);
}
static Cups cups1 = new Cups();
static Cups cups2 = new Cups();
}
无论是通过标为(1)的那行代码访问静态的cup1对象,还是把标为(1)的行注释掉,让它去运行标为(2)的那行代码(即解除标为(2)的行的注释),Cups的静态初始化动作都会得到执行。如果把标为(1)和(2)的行同时注释掉,Cups的静态初始化动作就不会进行。此外,激活一行还是两行标为(2)的代码(即解除注释)都无关紧要,静态初始化动作只进行一次。
数组初始化
数组初始化主要有两种形式。第一种如下:
//Aggregate initialization
BerylliumSphere[] d = { new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere()};
数组d表明使用"聚集初始化"语法创建数组对象,并且以BerylliumSphere对象将其初始化的过程,但是这个操作必须在定义d的位置使用。
第二种如下:
//Dynamic aggregate initialization
a = new BerylliumSphere[] {
new BerylliumSphere(), new BerylliumSphere()
};
这种方法被看作是"动态的聚集初始化",这种方法可以在任意位置创建和初始化数组对象。例如,假设方法hide()需要一个BerylliumSpere对象的数组作为输入参数。可以如下调用:
hide(d);
但也可以动态地创建将要作为参数传递的数组:
hide(new BerylliumSpere[]{new BerylliumSpere()}
双括号初始化(Java核心技术卷一,P243)
双括号初始化利用了内部类的语法。假设想构造一个数组列表,并将它传递到一个方法。
ArrayList<String> friends = new ArrayList<>();
friends.add("Harrys");
friends.add("Tony");
invite(friends);
如果不需要这个数组列表,最好让它作为一个匿名列表。不过作为一个匿名列表,添加元素方法如下:
invite(new ArrayList<String>(){{add("Harrys");add(""Tony"")}})
注意这里的双括号。外括号建立了Arraylist的一个匿名子类。内括号则是一个对象构造块。
【Java】初始化的更多相关文章
- Java初始化过程
这篇文章主要讲解Java在创建对象的时候,初始化的顺序.主要从以下几个例子中讲解: 继承关系中初始化顺序 初始化块与构造器的顺序 已经加载过的类的初始化顺序 加载父类,会不会加载子类 创建子类对象会不 ...
- Java初始化顺序
package com.helei.init; class Log { public static String fatherStaticString(){System.out.println(&qu ...
- (原)Java初始化过程
先看一个demo,然后进行归纳. class X{ static M m=new M(); Y y=new Y(); public X(){ System.out.print("X" ...
- Java初始化生命周期
package com.init; abstract class Glyph { void draw() { System.out.println("Glyph.draw()"); ...
- Java初始化理解与总结 转载
Java的初始化可以分为两个部分: (a)类的初始化 (b)对象的创建 一.类的初始化 1.1 概念介绍: 一个类(class)要被使用必须经过装载,连接,初始化这样的过程. 在装载阶段,类装载器会把 ...
- Java 初始化字段方式和顺序
Java 初始化字段方式和顺序: 类加载时直接初始化静态字段; 类加载时调用静态方法初始化静态字段; 实例化对象时,在调用构造函数之前代码块中初始化字段; 实例化对象时,在调用构造函数之时初始化字段; ...
- Java 初始化的个人理解
先说明一下由来吧,下面是同学的一道笔试题,以前感觉对java初始化也是了解一二的,结果,看到这题泪奔了,不会...上网查,自己添加println,总算是能把自己讲明吧了,不知理解的对不对,先记录下吧, ...
- [转]Java初始化顺序总结 - 静态变量、静态代码块、成员变量、构造函数
Java初始化顺序1在new B一个实例时首先要进行类的装载.(类只有在使用New调用创建的时候才会被java类装载器装入)2,在装载类时,先装载父类A,再装载子类B3,装载父类A后,完成静态动作(包 ...
- JAVA学习笔记(2)—— java初始化三个原则
1. 初始化原则 (1) 静态对象(变量)优先于非静态对象(变量)初始化,其中静态对象(变量)初始化一次,非静态对象(变量)可能会初始化多次. (2) 父类优先于子类初始化 (3) 按照成 ...
- Java初始化方法:类、容器
Java初始化方法:类.容器 初始化类(非final): Struts2的DefaultActionMapper类中: public DefaultActionMapper() { ...
随机推荐
- 使用verdaccio 搭建npm私有仓库
使用verdaccio 搭建npm私有仓库 1. 为什么要搭建私有的npm仓库? 随着公司的业务越来越复杂,项目迭代速度也越来越快,那么项目间的常用的业务代码共享变得非常之有必要.但是对于公司的 ...
- B-Tree外存数据结构 _(B 树)第二部分
2. B 树 B 树是为了磁盘或其它存储设备而设计的一种多叉(相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树 一棵B树,一棵关键字为英语中辅音字母的B树,现在要从树中查找字母R(包含n[x] ...
- AI 循环神经网络(RNN)
循环神经网络(Recurrent Neural Network,简称RNN),通常用于处理序列数据.正如卷积神经网络通常用于处理网格数据(例如图像)一样. 1.展开计算图 输入.输出.记忆 权值 2. ...
- [02] URL和HttpURLConnection类
1.URL的概念 统一资源定位符URL(Uniform Resource Locator)是www客户机访问Internet时用来标识资源的名字和地址. URL的基本格式是: <METHOD&g ...
- TCP/IP与OSI模型
- (译)理解 LSTM 网络 (Understanding LSTM Networks by colah)
@翻译:huangyongye 原文链接: Understanding LSTM Networks 前言:其实之前就已经用过 LSTM 了,是在深度学习框架 keras 上直接用的,但是到现在对LST ...
- 给 MSYS2 添加中科大的源
最近一段时间不知怎么的,使用默认的 MSYS2 源升级软件或是安装新软件的特别的慢.所以就翻了翻国内的几个开源软件的镜像库,发现中科大的库里就有 MSYS2.所以就研究了一下,给 MSYS2 添加了中 ...
- 重磅|0元学 Python运维开发,别再错过了
51reboot 运维开发又双叒叕的搞活动了,鉴于之前 51reboot 的活动反馈,每次活动结束后(或者已经结束了很长时间)还有人在问活动的事情.这一次小编先声明一下真的不想在此次活动结束后再听到类 ...
- 树莓派Opencv张正友棋盘标定法
make.Makefile cc = gcc #最简易的makefile文件,这个可以用来进行文件之间的简易构建和链接,生成我们所需要的执行文件: prom = calc deps = $(shell ...
- Redis常见问题和解决办法梳理
=============Redis主从复制问题和解决办法 ================= 一.Redis主从复制读写分离问题 1)数据复制的延迟读写分离时,master会异步的将数据复制到sla ...