zoukankan      html  css  js  c++  java
  • 【Java】构造方法和匿名对象

    前言

    在编写程序时不安全的初始化会导致程序发生发生重大错误。为了使程序可以被安全地初始化,C++引入了构造器(也可以成为构造方法)的概念,这是一个在创建对象时被自动调用的特殊方法。Java中也采用了构造器,并且提供了“垃圾回收器”。对不再使用的内存资源,垃圾回收器能自动将其释放。本文下面主要介绍Java的构造方法以及匿名对象。

    构造方法的定义语法与调用时机

    构造方法的定义语法及访问权限

    构造方法是在创建对象时被编译器自动调用,所以编译器应该知道构造方法的名字然后去调用它,为构造方法任意取名都可能会与类的某个成员冲突。于是Java采用了同C++中一样的方法:构造方法采用与类相同的名称

    构造方法一般定义为如下三种方式:

    class Student{
      public Student(){     //①
        ...
      }
      ...
    }
    class Student{
      Student(){      //②
        ...
      }
      ...
    }
    class Student{
      private Student(){    //③
        ...
      }
      ...
    }
    

    以上三种构造方式涉及到了访问权限的问题:

    第①种方式,构造方法采用了public修饰表示该类的对象是可以被不同包(package)的其他类创建。

    第②种方式,默认为包访问属性,仅限于同包的类可以创建该类的对象。

    第③种方式,使用private修饰使得构造方法对外不可见,无法在外部调用该类的构造器创建其实例。一般通过工厂模式创建该类实例。

    以上列举了三种访问权限访问修饰符,如果学过C++那旧还知道一种没有出现的访问权限修饰符就是protected。该修饰符表示本包中的类可访问,不同包中的子类可以访问。

    对包做一个解释:包类似于电脑中的文件夹,文件多了需要存于不同文件夹中方便管理,同样如此,类多了就需要放在不同的包里面方便管理,同时也避免了命名冲突问题。

    总结访问权限修饰符的可访问性:

    范围 private default(默认包访问) protected public
    同一个类 O O O O
    同一个包中的子类 X O O O
    同一个包中的其他类 X O O O
    不同包中的子类 X X O O
    不同包中的非子类 X X X O

    构造方法的调用时机(创建对象的初始化顺序)

    前面一直在说构造方法的调用是在类创建时,与普通方法不同,构造方法在实例化新对象(使用new开辟空间后)调用一次。普通方法在对象被实例化后可以调用多次。

    由于对初始化有不同的需求,因此构造方法也可重载的。

    下面跟踪一下构造方法被调用的过程:

    class Person{
    	  private long pid=123456789;
    	  public Person(){
    		  System.out.println("Person()");
    	  }
    	  public Person(long pid){
    		System.out.println("Person(long pid)");
    		System.out.println("在使用传进来的pid赋值前:pid:"+this.pid);
    	    this.pid = pid;
    	    System.out.println("在使用传进来的pid赋值后:pid:"+this.pid);
    	  }
    }
    public class Student extends Person{   //extends 实现继承关系
      private String name;
      private int age=0;
      public Student(){
    	  System.out.println("Student()");
      }
      public Student(long pid, String name, int age){
        super(pid);			//调用父类的构造函数一定要写在最前面不然会报错
        System.out.println("Student(long pid, String name, int age)");
        this.name = name;
        this.age = age;
      }
      public getName(){
        return name;
      }
      public static void main(String[] args){
        Student stu1 = new Student();
        Student stu2 = new Student(123456,"Sakura",20);
      }
    }
    /*
    output:
    Person()
    Student()
    Person(long pid)
    在使用传进来的pid赋值前:pid:123456789
    在使用传进来的pid赋值后:pid:123456
    Student(long pid, String name, int age)
    */
    

    可以输出结果看出Java中的初始化顺序如下:

    • 在任何其他事情发生之前,首先会将分配给对象的存储空间初始化成二进制零。
    • 调用基类的构造函数。
    • 按照声明顺序调用属性的初始化方法。在Person中先将pid赋值为1234556789然后在返回到构造函数中将123456赋值给pid。
    • 调用导出类的构造函数。若是Student中属性有给定初始值,那么依旧如第三步后再进入构造函数进行其他初始化操作。

    匿名对象

    什么是匿名对象?

    我们来看一步就创建对象的语法:

    ①类名称 ②对象名称 = ③new ④类名称()
    
    1. ①:规定了对象的类型
    2. ②:对象的名字,唯一标识对象
    3. ③:开辟新的堆内存空间,存储对象的内容
    4. ④:调用构造方法初始化对象

    上面的这条语句在内存中开辟了两个空间,一个栈空间存储引用变量对象名称,一个使用new开辟的堆空间用于存储对象内容。

    对象名称指向了在对堆中的对象,于是我们可以使用对象名称去操作对象

    若是我们只有"new 类名称();"这部分的话,那就是只是在堆中开辟了一个空间来保存对象信息,没有栈去指向它。也就是这个空间是没有名字的。所以简单来说,没有栈中引用指向的对象就叫做匿名对象

    匿名对象的使用

    new Student(123456,"Sakura",20).getName();
    

    由此就创建了一个匿名对象,可以向操作具名对象一样操作它。
    由于没有引用变量指向匿名对象,所以只能使用一次,然后就会成为垃圾对象等待被GC回收,

    小结

    总结了Java中构造方法的定义和作用(为了在类对象实例化时设置属性初始化)由此涉及到到类访问权限,然后对类访问权限做了一个小结,以及Java程序初始化的顺序。最后介绍了匿名对象,即没有栈中引用指向的对象。

    参考:

    [1] Eckel B. Java编程思想(第四版)[M]. 北京: 机械工业出版社, 2007

  • 相关阅读:
    Codeforces Round #258 (Div. 2) D. Count Good Substrings —— 组合数学
    Codeforces Round #394 (Div. 2) C. Dasha and Password —— 枚举
    Codeforces Round #394 (Div. 2) B. Dasha and friends —— 暴力 or 最小表示法
    Codeforces Beta Round #7 D. Palindrome Degree —— 字符串哈希
    VK Cup 2012 Qualification Round 1 E. Phone Talks —— DP
    Codeforces Beta Round #88 C. Cycle —— DFS(找环)
    Codeforces Round #178 (Div. 2) B. Shaass and Bookshelf —— DP
    VK Cup 2015
    Codeforces Round #173 (Div. 2) E. Sausage Maximization —— 字典树 + 前缀和
    python模块--ip地址转换为整数
  • 原文地址:https://www.cnblogs.com/myworld7/p/9977000.html
Copyright © 2011-2022 走看看