• 动手动脑 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 中已经存在此对象,所以,直接返回引用。

     

  • 相关阅读:
    问题001:Java软件,属于系统软件还是应用软件呢?
    Apache.Tomcat 调用Servlet原理之Class类的反射机制,用orc类解释
    CharSquence 接口的作用,多态以增强String
    eclipse环境Dynamic web module version 3.1版本的进步,简化Dynamic web object 中Servlet类的配置,不用web.xml配置<Servlet>
    tomcat.apache startup.bat闪退两种解决方法
    c++谭浩强教材教学练习例题1.2 求两数之和 为什么sum=a+b;sum的值为65538
    JSON格式自动解析遇到的调用方法问题.fromJson() ..readValue()
    shell command to replace UltraEdit
    根据内容最后一位进行排序
    利用left join 筛选B表中不包含A表记录
  • 原文地址:https://www.cnblogs.com/zhao-teng-ass/p/7695831.html
Copyright © 2020-2023  润新知