• 03-类与对象(动手动脑)


    一、类的构造函数

    1.测试代码:

     1 public class Test {
     2     public static void main(String[] args) {
     3         Foo obj1 = new Foo();
     4     }
     5 }
     6 
     7 class Foo{
     8     int value;
     9     public Foo(int initValue){
    10         value = initValue;
    11     }
    12 }

    2.测试截图:

      以上代码编译无法通过:

    错误信息为:“The constructor Foo() is undefined”(构造函数Foo()未定义)

    3.结论:

      

    二、类初始化规则:

    测试代码一:

     1 public class Test {
     2     public static void main(String[] args) {
     3         InitializeBlockClass obj = new InitializeBlockClass();
     4         System.out.println("field:" + obj.field);
     5     }
     6 }
     7 
     8 class InitializeBlockClass{
     9     {
    10         field = 200;
    11     }
    12     public int field = 100;
    13     /*public InitializeBlockClass(int value){
    14         this.field = value;
    15     }*/
    16     /*public InitializeBlockClass(){
    17         field = 300;
    18     }*/
    19 }

    执行结果:

      

    测试代码二:

     1 public class Test {
     2     public static void main(String[] args) {
     3         InitializeBlockClass obj = new InitializeBlockClass();
     4         System.out.println("field:" + obj.field);
     5     }
     6 }
     7 
     8 class InitializeBlockClass{
     9     public int field = 100;
    10     {
    11         field = 200;
    12     }
    13     /*public InitializeBlockClass(int value){
    14         this.field = value;
    15     }*/
    16     /*public InitializeBlockClass(){
    17         field = 300;
    18     }*/
    19 }

    执行结果:

      

    结论:

      如果没有构造函数对成员变量赋值,则成员变量的初值取决于 对该变量赋值的初始化代码块对变量定义初始值 的先后顺序,最终等于最后被赋予的值。

    测试代码三:

     1 public class Test {
     2     public static void main(String[] args) {
     3         InitializeBlockClass obj = new InitializeBlockClass(123);
     4         System.out.println("field:" + obj.field);
     5     }
     6 }
     7 
     8 class InitializeBlockClass{
     9     
    10     public int field = 100;
    11     public InitializeBlockClass(int value){
    12         System.out.println("field:" + this.field);
    13         this.field = value;
    14     }
    15     {
    16         field = 200;
    17     }
    18 }

    执行结果:

    结论:

      在本程序代码中,由构造函数输出的field为200,说明程序先执行了初始化代码块,后执行构造函数,再结合测试一、二得出结论:

      类初始化顺序为:先是初始化代码块对变量赋值和定义变量时赋值(取决于程序代码中二者先后位置),后执行构造函数。

    三、静态初始化块执行顺序:

    测试代码:

     1 class Root{
     2     static{
     3         System.out.println("Root的静态初始化块");
     4     }
     5     {
     6         System.out.println("Root的普通初始化块");
     7     }
     8     public Root(){
     9         System.out.println("Root的无参数的构造器");
    10     }
    11 }
    12 class Mid extends Root
    13 {
    14     static{
    15         System.out.println("Mid的静态初始化块");
    16     }
    17     {
    18         System.out.println("Mid的普通初始化块");
    19     }
    20     public Mid(){
    21         System.out.println("Mid的无参数的构造器");
    22     }
    23     public Mid(String msg){
    24         //通过this调用同一类中重载的构造器
    25         this();
    26         System.out.println("Mid的带参数构造器,其参数值:" + msg);
    27     }
    28 }
    29 class Leaf extends Mid
    30 {
    31     static{
    32         System.out.println("Leaf的静态初始化块");
    33     }
    34     {
    35         System.out.println("Leaf的普通初始化块");
    36     }    
    37     public Leaf()
    38     {
    39         //通过super调用父类中有一个字符串参数的构造器
    40         super("Java初始化顺序演示");
    41         System.out.println("执行Leaf的构造器");
    42     }
    43 
    44 }
    45 
    46 public class TestStaticInitializeBlock{
    47     public static void main(String[] args) {
    48         new Leaf();
    49     }
    50 }

    执行结果:

    结论:

      

      另外,执行顺序为:先从父类到子类依次执行静态初始化块,再从父类到子类依次执行普通初始化块和构造函数。

    四、如何在静态方法中访问类的实例成员

    测试代码:

     1 public class Test {
     2     public static void main(String[] args) {
     3         B.foo();
     4     }
     5 }
     6 class B{    
     7     public void foo2(){
     8         System.out.println("访问实例成员");
     9     }
    10     public static void foo(){
    11         B c = new B();
    12         c.foo2();
    13     }
    14 }

    执行结果:

    五、Integer的诡异特性:

    测试代码:

     1 public class StrangeIntegerBehavior 
     2 {   
     3     public static void main(String[] args)
     4     {   
     5         Integer i1=100;  
     6         Integer j1=100;       
     7         System.out.println(i1==j1);       
     8         Integer i2=129;        
     9         Integer j2=129;        
    10         System.out.println(i2==j2);    
    11     }
    12 }

    执行结果:

    原因分析:

      反编译结果:

      

      Integer.java中valueOf()源代码:

      

     1     /**
     2      * Returns an {@code Integer} instance representing the specified
     3      * {@code int} value.  If a new {@code Integer} instance is not
     4      * required, this method should generally be used in preference to
     5      * the constructor {@link #Integer(int)}, as this method is likely
     6      * to yield significantly better space and time performance by
     7      * caching frequently requested values.
     8      *
     9      * This method will always cache values in the range -128 to 127,
    10      * inclusive, and may cache other values outside of this range.
    11      *
    12      * @param  i an {@code int} value.
    13      * @return an {@code Integer} instance representing {@code i}.
    14      * @since  1.5
    15      */
    16     public static Integer valueOf(int i) {
    17         if (i >= IntegerCache.low && i <= IntegerCache.high)
    18             return IntegerCache.cache[i + (-IntegerCache.low)];
    19         return new Integer(i);
    20     }

       其中,IntegerCache为:

     1     /**
     2      * Cache to support the object identity semantics of autoboxing for values between
     3      * -128 and 127 (inclusive) as required by JLS.
     4      *
     5      * The cache is initialized on first usage.  The size of the cache
     6      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     7      * During VM initialization, java.lang.Integer.IntegerCache.high property
     8      * may be set and saved in the private system properties in the
     9      * sun.misc.VM class.
    10      */
    11 
    12     private static class IntegerCache {
    13         static final int low = -128;
    14         static final int high;
    15         static final Integer cache[];
    16 
    17         static {
    18             // high value may be configured by property
    19             int h = 127;
    20             String integerCacheHighPropValue =
    21                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    22             if (integerCacheHighPropValue != null) {
    23                 try {
    24                     int i = parseInt(integerCacheHighPropValue);
    25                     i = Math.max(i, 127);
    26                     // Maximum array size is Integer.MAX_VALUE
    27                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
    28                 } catch( NumberFormatException nfe) {
    29                     // If the property cannot be parsed into an int, ignore it.
    30                 }
    31             }
    32             high = h;
    33 
    34             cache = new Integer[(high - low) + 1];
    35             int j = low;
    36             for(int k = 0; k < cache.length; k++)
    37                 cache[k] = new Integer(j++);
    38 
    39             // range [-128, 127] must be interned (JLS7 5.1.7)
    40             assert IntegerCache.high >= 127;
    41         }
    42 
    43         private IntegerCache() {}
    44     }

    通过这两段代码可以看出,在通过valueof方法创建Integer类型对象时,取值范围为[-128,127],数值在这个区间里,指针指向IntegerCache.cache中已经存在的对象引用,当数值超出这个范围,就会创建一个新的对象。而对对象使用“==”是判断两个对象是否是同一个,所以i1 == j1,i2 != j2。

  • 相关阅读:
    错误代码 0x800700b7 配置错误定义了重复的“system.web.extensions/scripting/scriptResourceHandler”节
    字符型设备驱动程序-first-printf以及点亮LED灯(一)
    翻译 TI SerialBLEbridge V 1.4.1
    lwip TCP client & FreeRTOS 打开TCP 的 保活机制 LWIP_TCP_KEEPALIVE==1
    lwip TCP client 客户端 & FreeRTOS
    CC2540 OSAL 学习其中原理,以及 给任务 添加 一个事件(定时发送串口消息)
    跟我一起学Linux-线程创建,类似FreeRTOS创建任务
    用 S5PV210 学习 Linux (三) SD卡下载
    用 S5PV210 学习 Linux (二) 刷机(二)
    用 S5PV210 学习 Linux (一) 刷机(一)
  • 原文地址:https://www.cnblogs.com/lzq666/p/7697802.html
Copyright © 2020-2023  润新知