动手动脑 3 类与对象

   

                                 动手动脑  3  类与对象

           一、构造函数的调用

                  

          

          原因&解法

     如果类没有定义构造函数,Java编译器在编译时会自动给它提供一个没有参数的“默认构造方法”。构造函数未定义时,调用Object父类中的默认构造,若用户自己定义时了有参构造函数,Object父类中的默认构造失效,所以需要用户自己写无参构造函数。所以上面的foo类需再定义空参构造,才可成功调用。

     如下代码:

     

package 课件程序二;
public class Test {
    public static void main(String[] args) {
        Foo obj1=new Foo();
    }
}
class Foo
{
   int value;
   public Foo(int initValue)
   {
       value=initValue;
   }
   public Foo() {}//用户需自己定义无参构造,因为用户自定义的实参构造,导致系统的默认构造失效
}

  二、初始化执行顺序

 

       代码如下:

          

           

public class InitializeBlockDemo {
    public static void main(String[] args) {
        
        InitializeBlockClass obj=new InitializeBlockClass();
        System.out.println(obj.field);
        
        obj=new InitializeBlockClass(300);
        System.out.println(obj.field);//输出当前field的值
    }

}

class InitializeBlockClass{
    //下面这句在初始化块之前与之后,会影响到field字段的初始值   
    //public int field=100;
    
    {
        field=200;
    }
    public int  field=100;
    public InitializeBlockClass(int value){
        this.field=value;
    }
    public InitializeBlockClass(){
        
    }
}

   执行结果:

    

  

  过程分析:

  在上述代码中,变量值以最终所存的值做最终值,虽然刚开始在执行体中给field赋值200,之后又重新赋值100,所以obj.field的第一次输出field为后者100,而obj重新初始化,开辟新空间,储存新的值,调用实参构造,改变以前field,将参数赋给field,所以obj.field的第二次输出为300。

  

  静态初始化块的执行顺序:

    1.静态初始化块只执行一次。

    2.创建子类型的对象时,也会导致父类型的静态初始化块的执行

  总结:静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法注意***子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。

  三、类的静态方法只能访问类的静态成员!

  1.提出问题:

    静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

  2.解决方法:

    只需创建该类的对象,再以对象名.变量名/方法名访问即可。

  3.检验代码如下:

package 课件程序二;

public class MyTestClass {
     int value=1;
    int set(int n)
    {
        value=n;
        return value;
    }
    static void display()
    {
        MyTestClass Test1=new MyTestClass();//实例化对象,利用对象.变量名/方法名访问
        System.out.println("成员(字段)调用  "+Test1.value);
        System.out.println("成员(方法)调用  "+Test1.set(10));
    }
    public static void main(String[] args) {
        display();
    }
}

  结果截图:

                   

     四、Integer的特异性

            

             

    java中变量有两种类型

      1.基本类型(int,double等)

        基本数据类类型存的是数值本身

      2.引用类型(赋值,new,类的创建等)

        引用类型变量在内存放的是数据的引用

      基本类型通过==比较的是他们的值大小,而引用类型比较的是他们的引用地址

    如:

          

public class StrangeIntegerBehavior 
{ 
    public static void main(String[] args)
    {
        Integer i=-128;
        //Integer.valueOf(128);
        Integer j=-128;
        System.out.println(i==j);
        Integer i1=100;
        Integer j1=100;
        System.out.println(i1==j1);
        Integer i2=129;
        Integer j2=129;
        System.out.println(i2==j2); 
    }
}

 

  结果截图:

                    

  当我们给一个Integer赋予一个int类型的时候会调用Integer的静态方法valueOf。 

  Integer i1= Integer.valueOf(-128); 

  Integer i2 = Integer.valueOf(200); 
  Integer i3 = Integer.valueOf(15); 
  Integer i4 = Integer.valueOf(127); 
  思考:那么Integer.valueOf()返回的Integer是不是是重新new Integer(num);来创建的呢?如果是这样的话,那么== 比较返回都是false,因为他们引用的堆地址不一样。

  Jdk中Integer.valueOf的源码

        

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}

    IntegerCache中cache数组初始化如下,默认存入了-128 - 127的值

  

cache = new Integer[(high - low) + 1];int j = low;for( int k = 0; k < cache.length ; k ++)
cache[k] = new Integer(j ++);

  Integer i1=100 的时候,会调用 Integer 的 valueOf 方法,这个方法就是返回一个 Integer 对象,只是在返回之前,看作了一个判断,判断当前i 的值是否在 [-128,127] 区别,且 IntegerCache 中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象

  从上面我们可以知道给Interger 赋予的int数值在-128 - 127的时候,直接从cache中获取,这些cache引用对Integer对象地址是不变的,但是不在这个范围内的数字,则new Integer(i) 这个地址是新的地址,不会相同。

上述代码分析

I2= j2分析 
Integer i2 = 129; 自动调用Integer.valueOf(129) 返回一个Integer的对象。 这个对象存放到cache中的(上面一段代码分析)。 而 Integer i2= new Integer(129)这里创建了一个新的对象Integer ,同理j1的操作相同,两者开创空间不同,地址不同,所以 i2== j2 返回的是false

i1==j1 分析 

Integer i1=100 的时候,会调用 Integer 的 valueOf 方法,在这里的话,因为程序初次运行,没有 59 ,所以,直接创建了一个新的对象,判断59在-128~127中,返回引用,i2与i1操作相同,返回相同,所以结果为true。

 注意Integer 对象与int 比较时,比较的不是地址,而是值。 Integer 会自动拆箱成int ,然后进行值的比较。 Integer i3 =Integer.valueOf(59);时 因为 IntegerCache 中已经存在此对象,所以,直接返回引用。

 

原文地址:https://www.cnblogs.com/zhao-teng-ass/p/7695831.html