zoukankan      html  css  js  c++  java
  • 动手动脑——类与对象

     以下代码为何无法通过编译?哪儿出错了?

    public class Test{
        public static void main(String[] args) {
            Foo obj1 = new Foo();
        }
    }
    class Foo{
        int value;
        public Foo(int initValue){
            value=initValue;
        }
    }

    以下为Editplus提示的错误信息:
    ---------- javac ----------
    Test.java:3: 错误: 无法将类 Foo中的构造器 Foo应用到给定类型;
    Foo obj1 = new Foo();
    ^
    需要: int
    找到: 没有参数
    原因: 实际参数列表和形式参数列表长度不同
    1 个错误

    输出完成 (耗时 0 秒) - 正常终止

      如果自定义类内存在一个自定义构造方法,那么系统将不再提供默认的无参构造方法。所以当定义一个有参的构造方法时,应当注意需要再定义一个无参的构造方法。

    以下代码输出结果是什么?总结Java字段初始化的规律

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

      如果   public int field=100;   这句在初始化块之前,则结果为200   300;如果在之后则结果为100   300。定义变量和初始化这几句我是这样理解的:

    public int field;    //public int field=100;这句在前相当于这几句
    {
        field=100;
    }
    {
        field=200;
    }
    public int field;    //public int field=100;这句在后相当于这几句
    {
        field=200;
    }
    {
        field=100;
    }

      按照我的理解,创建对象时,首先对成员变量进行默认初始化,然后按照代码先后顺序进行初始化,最后进行构造方法内的变量初始化。

      使用局部变量时,如果变量为非数组形式的变量且未进行初始化,编译器会提示局部变量未初始化;如果变量为数组形式的变量且未进行初始化则不会提示局部变量未初始化,因为编译器已经进行了默认的初始化。而在类中,无论是否为数组形式的变量,成员变量始终会进行默认初始化。

      byte,short,int,long默认初始化值为0;float,double默认初始化值为0.0;boolean默认初始化值为false;char默认初始化值’u0000’Unicode码的空格)或0(ASCII码的空格);String默认初始化值为null。

    运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”

    class Root
    {
        static{
            System.out.println("Root的静态初始化块");
        }
        {
            System.out.println("Root的普通初始化块");
        }
        public Root()
        {
            System.out.println("Root的无参数的构造器");
        }
    }
    class Mid extends Root
    {
        static{
            System.out.println("Mid的静态初始化块");
        }
        {
            System.out.println("Mid的普通初始化块");
        }
        public Mid()
        {
            System.out.println("Mid的无参数的构造器");
        }
        public Mid(String msg)
        {
            //通过this调用同一类中重载的构造器
            this();
            System.out.println("Mid的带参数构造器,其参数值:" + msg);
        }
    }
    class Leaf extends Mid
    {
        static{
            System.out.println("Leaf的静态初始化块");
        }
        {
            System.out.println("Leaf的普通初始化块");
        }    
        public Leaf()
        {
            //通过super调用父类中有一个字符串参数的构造器
            super("Java初始化顺序演示");
            System.out.println("执行Leaf的构造器");
        }
    }
    public class TestStaticInitializeBlock
    {
        public static void main(String[] args) 
        {
            new Leaf();
            System.out.println("****************************************************");
            new Leaf();
        }
    }

      根据运行结果可知:静态代码块总是最先执行,且无论创建多少个对象,静态代码块只执行一次,其次执行构造代码块,最后执行构造方法。无论子类是否调用父类构造方法,父类的所有构造代码块、构造方法均先于子类的构造代码块、构造方法执行。静态代码块也遵循父类先于子类执行的特点。如果子类存在调用父类的有参构造方法,那么执行父类构造方法时就不会执行无参构造方法(使用this()调用除外)。

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

      可以通过将类实例化或者使用匿名类来访问类的实例成员。

    public class Test {
        public static void main(String[] args) {
            Myclass mc = new MyClass();
            System.out.println(mc.str);
            mc.function();
            System.out.println(new MyClass().str);
            new MyClass().function();
        }
    }
    class MyClass{
        public String str="这是非静态的成员变量";
        public void function() {
            System.out.println("这是非静态的成员方法");
        }
    }

     两对整数明明完全一样,为何一个输出true,一个输出false?

    public class StrangeIntegerBehavior {
        public static void main(String[] args){
            Integer i1=100;      //相当于Integer i1=Integer.valueOf(100);
            Integer j1=100;      //相当于Integer j1=Integer.valueOf(100);
            System.out.println(i1==j1);    //true
            Integer i2=129;      //相当于Integer i2=new Integer(129);
            Integer j2=129;      //相当于Integer j2=new Integer(129);
            System.out.println(i2==j2);    //false
        }
    }

      Integer类内有个东西叫常量池。在为Integer类变量赋值时,若取值在-128到127内,则会在常量池中寻找内存地址,如果取值不在常量池内(即-128到127),则会为变量开辟新的内存空间来存值。以下为Integer类的赋值方法

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    public Integer(int value) {
         this.value = value;
    }
  • 相关阅读:
    每天读一下,你就会改变
    C++ 反转字符串(原创)
    C++ string学习
    18种常见室内花卉的功效 (转自网络)
    UML建模教程
    孙鑫视频VC++深入详解学习笔记
    visual C++ 6.0开发工具与调试
    C++ typeid typename使用
    C++模板学习
    Working classes Code complete reading notes(6)
  • 原文地址:https://www.cnblogs.com/dream0-0/p/9821239.html
Copyright © 2011-2022 走看看