Java学习笔记之浅谈初始化

          在Java中,通过提供构造器,类的设计者可确保每个对象都会得到初始化。在Java中,构造器与类同名,且没有返回值。

1.默认构造器   

      默认构造器是没有形式参数的,作用就是创建一个默认对象。如果你写的类中没有构造器,则编译器会自动帮你创建一个默认构造器,如下:

public class ConstructorDemo1 {
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
ConstructorDemo1 demo1 = new ConstructorDemo1();
}
}

但是,一旦你拥有自己的构造器,则编译器就不会为你提供构造器,因为编译器知道你已经提供了构造器,就不要它自作多情了。如下:

public class ConstructorDemo1 {
public ConstructorDemo1() {
// TODO Auto-generated constructor stub
System.out.println("Constructor!!!");
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
ConstructorDemo1 demo1 = new ConstructorDemo1();
}
}

2.this关键字

this关键字只能在方法内部使用,表示对“调用方法的那个对象”的那个引用。this用法和其他对象引用并无不同,如果在方法内部调用同一个类的另一个方法,就不必使用this,直接调用即可。

public class ConstructorDemo1 {
String s = "Hello";
public ConstructorDemo1(String s) {
// this.s = s;
s = "Hello World";
System.out.println(s);
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
ConstructorDemo1 demo1 = new ConstructorDemo1(new String());
System.out.println(demo1.s);
}
}

output:

Hello World

Hello

从上面的结果会觉得很奇怪,因为demo1的s竟然不是Hello World,这是因为构造器中的形参s与成员变量s同名,隐藏了类的成员变量,才造成了数据成员s并没有改变的原因。

这很明显与我们的意愿不符合,我们希望通过构造器改变s的值,那么有什么方法可以在形参名与数据成员变量名相同时达到我们预期的效果呢?这就需要用到this关键字。

public class ConstructorDemo1 {
String s = "Hello";
public ConstructorDemo1(String s) {
this.s = s;
System.out.println(s);
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
ConstructorDemo1 demo1 = new ConstructorDemo1("Hello World");
System.out.println(demo1.s);
}
}

output:

Hello World

Hello World

只有当需要明确指出对当前对象的引用时,才需要使用this关键字。

3.在构造器中调用构造器

       当一个类有很多构造器时,可能会需要在一个构造器中调用另一个构造器,以避免重复代码,可以用this关键字做到。

public class Person {
String name;
int age;
boolean isFemale;
public Person(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
public Person(String name, int age) {
// TODO Auto-generated constructor stub
this(name);
this.age = age;
}
//public Person(String name, int age, boolean isFemale) {
 TODO Auto-generated constructor stub
//this(name);
//this(name, age);
//this.isFemale = isFemale;
//}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
Person person = new Person("Tom", 22);
System.out.println(person.name);
System.out.println(person.age);
}
}

在构造器里,为this添加了参数列表,这就调用了某个构造器。但是,尽管可以使用this低啊用一个构造器,但却不能调用两个(如上面代码注释处的构造函数)。此外,必须将构造器低啊用置于最起始处,即第一句代码,否则编译器报错。

4.static关键字

static用于限定成员变量和方法,static表示域或者方法是属于类的,而不是属于某个对象。在static方法内部不能调用非静态方法,反过来倒是可以。由于static是属于类的,所以既可以通过类名调用也可以通过对象调用。

public class StaticTest {
static int i;
public StaticTest() {
++i;
// TODO Auto-generated constructor stub
}
static void print() {
System.out.print(i + "  ");
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticTest[] tests = { new StaticTest(), new StaticTest(),
new StaticTest(), new StaticTest() };
for (StaticTest test : tests) {
test.print();
StaticTest.print();
System.out.print(test.i + "  ");
System.out.print(StaticTest.i + "\n");
}
}
}

output:

4  4  4  4

4  4  4  4

4  4  4  4

4  4  4  4

从上面代码可以看到既可以通过对象也可以通过类名来调用静态域和方法。由于静态域和方法属于类,所以所有对象共享一份变量,每个i变量都变成了4.

5.成员初始化

Java尽力保证,所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误来保证。但要是类的数据成员(即字段)是基本类型,则Java会提供一个默认值保证初始化,而对于对象引用,会赋值一个null的初始值。

byte b;
short s;
int i;
long l;
float f;
double d;
char c;
boolean bool;
Person person;
void printValues() {
System.out.println("byte b=" + b);
System.out.println("short a=" + s);
System.out.println("int i=" + i);
System.out.println("long l=" + l);
System.out.println("float f=" + f);
System.out.println("double d=" + d);
System.out.println("char c=" + c);
System.out.println("booolean bool=" + bool);
System.out.println("Person person=" + person);
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
new ConstructorDemo1().printValues();
}

output:

byte b=0

short a=0

int i=0

long l=0

float f=0.0

double d=0.0

char c=[]

bollean bool=false

Person person=null

除了使用Java为我们提供的自动初始化,我们也可以在申明变量的时候进行指定初始化。

另外,我们可以通过构造器进行初始化。但要牢记,无法阻止自动初始化的进行,它将在构造器被调用之前发生。

class Couter {
int i;
public Couter() {
i = 7;
}
}

i首先会被置为0,然后变成7。

   a.初始化顺序

       在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

   b.静态数据的初始化

        无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此只能作用于域。如果一个域是静态的基本类型与,且也没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始化值就是null。

        静态域只会被初始化一次(无论创建对象还是通过类名引用静态域或者方法),并且是在非静态变量之前。

    c.静态初始化块

        Java允许将多个静态初始化动作组织成一个特殊的“静态块”。

static String name;
static float f;
static {
name = "wall";
f = 1.0f;
}

与其他静态初始化动作一样,这段代码只执行一次,当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即使未生成过那个类的对象)。

总结:

Java是一种面向对象的语言,以类来封装数据成员和方法。而初始化一个对象是一件很重要的事情,为此Java做了很多让初始化安全的方法。方法操作数据,所以在可以调用方法之前确保所有域的初始化才是关键。这样我们也可以将构造器看做一种特殊的方法。也就是说数据成员的初始化也是在构造器之前的,而为了确保数据成员的正确初始化,Java通过提供默认值得方式来保证,这样,即使我们忘记或者不需要初始化时,依然可以正确的操作数据。而对于静态域,由于它是属于类的,当我们创建一个对象时,肯定是首先得知道它所属于哪个类,所以类的数据成员得在对象的数据成员之前得到初始化,也就是上面说的初始化顺序。这篇博客讲的是一个类的初始化相关问题,过段时间会写关于继承中的初始化问题。我们都可以通过为了使初始化安全为目的的思路来理解数据成员的初始化。




转载于:https://my.oschina.net/992257586/blog/342232

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值