转载-定义时初始化和构造器初始化的差异

  1. 概述

    1. 在Java中使用一个变量时,如果我们不给变量初始化,则编译器会自动给变量初始化赋值,使得所有的变量在使用前都能得到恰当的初始化。
    2. 对于方法中的局部变量,如果不初始化就使用,则会报错(类似“The local variable i may not have been initialized”的错误信息)。
  2. 举例
    1. Dog类代码如下:

      public class Dog implements Serializable {
      
      private static final long serialVersionUID = 2239821175446189806L;
      private String kind;
      private String name = "jack";
      private int i;
      private double d;
      private float f;
      private byte b;
      private short s;
      private long l;
      private char c;
      private boolean bl;
      private Order order;
      
      public Dog() {
      System.out.println(this.name);
      System.out.println(this.kind);
      this.kind = "哈士奇";
      System.out.println(this.kind);
      System.out.println("编译器为int类型设置的初始化默认值为:" + i);
      System.out.println("编译器为double类型设置的初始化默认值为:" + d);
      System.out.println("编译器为float类型设置的初始化默认值为:" + f);
      System.out.println("编译器为byte类型设置的初始化默认值为:" + b);
      System.out.println("编译器为short类型设置的初始化默认值为:" + s);
      System.out.println("编译器为long类型设置的初始化默认值为:" + l);
      System.out.println("编译器为char类型设置的初始化默认值为:" + c);
      System.out.println("编译器为boolean类型设置的初始化默认值为:" + bl);
      System.out.println("编译器为引用类型(如Order)设置的初始化默认值为:" + order);
      }
      
      public Dog(String name) {
      this.name = name;
      }
      
      public String getKind() {
      return kind;
      }
      
      public void setKind(String kind) {
      this.kind = kind;
      }
      
      public String getName() {
      return name;
      }
      
      public void setName(String name) {
      this.name = name;
      }
      
      public Order getOrder() {
      return order;
      }
      
      public void setOrder(Order order) {
      this.order = order;
      }
      
      }

    2. Order代码如下:

      public class Order implements Serializable {
       2
       3     private static final long serialVersionUID = 7441323999887439757L;
       4
       5     private String orderNo;
       6     private String orderType;
       7
       8     public Order( String str) {
       9         System.out.println(str);
      10     }
      11
      12     public String getOrderNo() {
      13         return orderNo;
      14     }
      15
      16     public void setOrderNo(String orderNo) {
      17         this.orderNo = orderNo;
      18     }
      19
      20     public String getOrderType() {
      21         return orderType;
      22     }
      23
      24     public void setOrderType(String orderType) {
      25         this.orderType = orderType;
      26     }
      27 }

       1 public class Order implements Serializable {
       2
       3     private static final long serialVersionUID = 7441323999887439757L;
       4
       5     private String orderNo;
       6     private String orderType;
       7
       8     public Order( String str) {
       9         System.out.println(str);
      10     }
      11
      12     public String getOrderNo() {
      13         return orderNo;
      14     }
      15
      16     public void setOrderNo(String orderNo) {
      17         this.orderNo = orderNo;
      18     }
      19
      20     public String getOrderType() {
      21         return orderType;
      22     }
      23
      24     public void setOrderType(String orderType) {
      25         this.orderType = orderType;
      26     }
      27 }

    3. 执行类代码如下:

      public class Test {
      2     public static void main(String[] args) {
      3         Dog d = new Dog();
      4     }
      5 }

      1 public class Test {
      2     public static void main(String[] args) {
      3         Dog d = new Dog();
      4     }
      5 }
    4. 执行结果如下图:
    5. 分析如下:
      1. 由Dog类代码可知,成员变量kind是在构造方法中初始化的,成员变量name是在定义时初始化的,其他变量则没有初始化。
      2. 在main方法中创建了Dog对象,将调用构造方法。
      3. 构造方法中第一行代码是打印成员变量name的值,由于name在定义时就初始化了,所以name的值就是其定义时初始化的值“jack”;
      4. 构造方法中第二行代码是打印成员变量kind的值,虽然kind没有在定义时初始化,但是上图显示的结果却是null,这说明编译器为kind初始化了一个null值。
      5. 构造方法中第三行代码则是为kink赋值为“哈士奇”,所以第四行代码自然而然的打印出了kind的值是“哈士奇”。
      6. 构造方法的第五行代码之后,都是打印的未初始化的变量的值,由上面截图可知,虽然没有给这些变量赋值,但是他们却都打印出了值。
    6. 结论:
      1. 如果我们没有给变量赋值,则编译器会自动为每个变量赋一个恰当的值,具体情况如下:

        1. int类型的初始化默认值是 0   
        2. double类型的初始化默认值是 0.0d
        3. float类型的初始化默认值是 0.0f
        4. byte类型的初始化默认值是 0
        5. short类型的初始化默认值是 0
        6. lang类型的初始化默认值是 0
        7. char类型的初始化默认值是 “\0000”
        8. boolean类型的初始化默认值是 false
        9. 引用类型(如Order)的初始化默认值是 null
        10. 另外,数组引用类型的变量的默认值为 null。当数组变量实例化后,如果没有没有显示的为每个元素赋值,Java 就会把该数组的所有元素初始化为其相应类型的默认值。
      2. 定义时初始化和构造器初始化的差异:变量定义时初始化的次数是一次,如上面的变量name;而构造器初始化的次数是两次,首先编译器发现kind没有初始化,自动为kind赋null值,然后在构造方法中,再次初始化为“哈士奇”。

注:此文章为转载内容,原网址见:http://www.cnblogs.com/yanglz528/p/7821837.html

原文地址:https://www.cnblogs.com/silence-fire/p/8176748.html

时间: 2024-11-07 09:25:46

转载-定义时初始化和构造器初始化的差异的相关文章

GO学习笔记 - 变量在定义时没有明确的初始化时会赋值为“零值 ”。

官方教程:https://tour.go-zh.org/basics/12 变量在定义时没有明确的初始化时会赋值为 零值 . 零值是: 数值类型为 0 , 布尔类型为 false , 字符串为 "" (空字符串). 官方示例: package main import "fmt" func main() { //下面声明的变量没有被初始化,但是也具有值,就是默认的零值 var i int var f float64 var b bool var s string fm

Java中在类定义时对HashSet的初始化方法

Java中很多时候都要用到HashSet的查找功能,那么在类的定义时,数据成员假如就是HashSet类型的,我们定义数据成员之后,不好直接调用add函数来实现初始化,这个时候怎么办? 我们可以这样来做: public static final HashSet<String> salesWords = new HashSet<String>() {{ add("销售额"); add("销售"); add("销售金额"); a

java在类定义时对hashset的便捷初始化方法

有时候我们在类成员定义时,当这个类成员类型为 HashSet时,我们可以不方便调用 add函数进行初始化,所以可以采用下面的便捷方式来进行初始化 1 public class MyTest{ 2 3 final HashSet<String> set = new HashSet<String>() { 4 { 5 add("a"); 6 add("b"); 7 add("c"); 8 9 } 10 }; 11 public

Chapter5_初始化与清理_用构造器初始化

接下来进入第五章,java中初始化和清理的问题,这是两个涉及安全的重要命题.初始化的功能主要是为库中的构件(或者说类中的域)初始化一些值,清理的功能主要是清除程序中不再被需要的元素,防止资源过分被垃圾占用的出现,为解决这些问题,java中提供了对构造器和垃圾清理器的支持,首先讨论构造器的问题. 为了保证程序的安全性,java中采用了构造器的机制来保证初始化.第一个问题就是命名的问题,java中的构造器规定名称必须和类名相同.这主要是出于如下的考虑,第一如果让编程者自行命名,则可能会产生于其他任何

Chapter5_初始化与清理_构造器初始化

一.构造器初始化的基本顺序 在使用构造器进行初始化时,最需要注意的是初始化的顺序,这种方法可以给初始化的顺序带来很大的灵活性.看如下的一个例子. 1 class Window{ 2 Window(int marker){ 3 System.out.println("Window(" + marker + ")"); 4 } 5 } 6 7 class House{ 8 Window w1 = new Window(1); 9 House(){ 10 System.o

Java中String初始化了String域 和 构造器初始化的String域的差异

这是 java编程思想 第五章---初始化与清理 的一题 练习2 : 创建一个类,它 包含了一个定义时就被初始化了的String域,以及另一个通过构造器初始化的String域,这两种方式有何差异. 看这一段程序以及结果, 首先明确三个知识点: 1.String是引用对象 2.equals() 比较的是值 3. "=="是比较的 地址 String s1 = "abc"; String s2 = "abc"; String s3 = new Str

当一个非静态的成员是常量或是引用类型时,需要怎么样初始化它们

const int a ;//此句代码是错误的,因为const修饰的a必须要在定义的时候初始化. int &a;//同理,也是错的,在定义的时候必须要初始化,其他类型的数据也是一样. 那么如果一个类的成员有非静态const类型,或者引用类型时,该怎么初始化呢? #include<iostream>using namespace std;class A {  public: const int a;  A (int t){    a=t;   }};int main(){  A b(3)

OC03-继承,便利构造器,初始化方法

继承 继承 继承的主要作用就是保证类的完整以及简化代码. 使用时把公共的方法和实例变量写在父类里,子类只需要写自己独有的实例变量和方法就行 特点: 只允许单继承 OC中的根类是NSObject 继承的内容:是所有实例变量和方法 如果子类中不想用父类方法的实现,可以重写方法 注意: 继承的上层是父类,下层是子类 继承是单向的,不能相互继承 继承是有传递性的,即如果A继承于B,B继承于C,A就具有B和C的特征和行为 子类可以继承父类全部的特征和行为 继承的实现 #import <Foundation

定义一个字符数组并初始化,统计字符&#39;a&#39;或&#39;A&#39;出现的次数

1 package com.imooc.array; 2 3 public class SortDemo2 { 4 5 public static void main(String[] args) { 6 //定义一个字符数组并初始化,统计字符'a'或'A'出现的次数 7 //定义一个字符数组ch并初始化 8 char[] ch={'a','b','c','A','a','d','a','e','f','g'}; 9 //循环遍历数组,统计字符'a'或'A'出现的次数 10 int sum=0;