zoukankan      html  css  js  c++  java
  • 基本知识《一》继承初始化过程

    一、动态语言与静态语言的区别

    静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求. 动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
    动态语言目前非常具有活力。众所周知的ECMAScriptJavaScript)便是一个动态语言,除此之外如PHPRubyPython等也都属于动态语言,而CC++等语言则不属于动态语言。

    二、对象与内存控制

    成员变量:实例变量和类变量
    局部变量:形参,方法中的变量,代码块中的变量
    一个类只为一个类变量分配一块内存,二实例变量在每次实例化对象时都会分配一块内存空间
    三种初始化的方式
    public class Cat {
    //实例变量
        String name;
        int age;
    //类变量
        static int eyeNum=2;
    //构造函数初始化
        public Cat(String name, int age) {
            this.name = name;
            this.age = age;
        }
    //指定初始化值
        double weight = 2.3;
    //初始化块
        {
            System.out.println("非静态初始化实例变量");
            weight = 2;
        }
    
        public String tostring() {
            return "name:" + name + "
    " + "age:" + age + 
                    "
    " + "weight:" + weight+ "
    " + "eyeNum:" + eyeNum;
    
        }
    }
    
    public class lesson2variable {
    
        public static void main(String[] args) {
            Cat kitty = new Cat("kitty", 12);
            Cat hello = new Cat("hello", 12);
            System.out.println(kitty.tostring());
        }
    }
    View Code

    三、构建器的初始化

    为什么要引入构建器,为了方便程序更加灵活,在运行期间也可以对变量进行赋值,从而“现场”决定初始值。在一个类里,初始化的顺序是由变量在类中的顺序决定的,即使变量定义大量遍布在方法定义的中间,那些变量的初始化仍然会调用任何方法之前得到初始化,---甚至在构建器之前。

    class Tag {
    Tag(int marker) {
    System.out.println("Tag(" + marker + ")");
    }
    }
    
    public class Card {
        Tag t1 = new Tag(1); // Before constructor
        Card() {
        // Indicate we're in the constructor:
        System.out.println("Card()");
        t3 = new Tag(33); // Re-initialize t3
        }
        Tag t2 = new Tag(2); // After constructor
        void f() {
        System.out.println("f()");
        }
        Tag t3 = new Tag(3); // At end
    }
    
    public class Main {
    public static void main(String[] args) {
    Card t = new Card();
    t.f(); // Shows that construction is done
    }
    }
    
    运行结果:
    Tag(1)
    Tag(2)
    Tag(3)
    Card()
    Tag(33)
    f()
    View Code

    四、类变量和实例变量的初始化

    类变量的初始化在一个类被初始化时,JVM对每个类只初始化一次,类变量只分配一次内存空间,执行一次初始化,

    public class Price {
        final static Price InstancePRICE=new Price(2.8);//凡事讲究先来后到,此时initPrice已分配内存,但是还没有进行初始化赋值
        static double  initPrice=20;
        double currentPrice;
        public Price(double discount){
            System.out.println("正在执行构造器"+this.initPrice);
            System.out.println(Price.InstancePRICE.currentPrice);
            currentPrice=initPrice-discount;
        }
    }
    //主程序
    public class TestPrice {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println(Price.InstancePRICE.currentPrice);
            Price p1=new Price(2.8);
            System.out.println(p1.currentPrice);
        }
    }
    
    运行结果:
    正在执行构造器0.0
    -2.8
    -2.8
    正在执行构造器20.0
    17.2
    View Code

    总结:static 初始化只有在必要的时候才会进行。如果不创建一个Table 对象,而且永远都不引用Table.b1 或
    Table.b2,那么static Bowl b1 和b2 永远都不会创建。然而,只有在创建了第一个Table 对象之后(或者
    发生了第一次static 访问),它们才会创建

    class Bowl {
    Bowl(int marker) {
    System.out.println("Bowl(" + marker + ")");
    }
    void f(int marker) {
    System.out.println("f(" + marker + ")");
    }
    }
    
    class Table {
    static Bowl b1 = new Bowl(1);
    Table() {
    System.out.println("Table()");
    b2.f(1);
    }
    void f2(int marker) {
    System.out.println("f2(" + marker + ")");
    }
    static Bowl b2 = new Bowl(2);
    }
    
    class Cupboard{
    Bowl b3 = new Bowl(3);
    static Bowl b4 = new Bowl(4);//初始化的顺序是首先static(如果它们尚未由前一次对象创建过程初始化),接着是非static 对象
    Cupboard() {
    System.out.println("Cupboard()");
    b4.f(2);
    }
    void f3(int marker) {
    System.out.println("f3(" + marker + ")");
    }
    static Bowl b5 = new Bowl(5);
    }
    
    public class StaticInitialization {
    public static void main(String[] args) {
    System.out.println(
    "Creating new Cupboard() in main");
    new Cupboard();
    System.out.println(
    "Creating new Cupboard() in main");
    new Cupboard();
    t2.f2(1);
    t3.f3(1);
    }
    static Table t2 = new Table();
    static Cupboard t3 = new Cupboard();
    } ///:~
    
    运行结果:
    Bowl(1)
    Bowl(2)
    Table()
    f(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    Creating new Cupboard() in main
    Bowl(3)
    Cupboard()
    f(2)
    f2(1)
    f3(1)
    View Code

    总结:

    初始化的顺序是首先static(如果它们尚未由前一次对象创建过程初始化),接着是非static 对象。大家
    可从输出结果中找到相应的证据。
    在这里有必要总结一下对象的创建过程。请考虑一个名为Dog 的类:
    (1) 类型为Dog 的一个对象首次创建时,或者Dog 类的static 方法/static 字段首次访问时,Java 解释器
    必须找到Dog.class(在事先设好的类路径里搜索)。
    (2) 找到Dog.class 后(它会创建一个Class 对象,这将在后面学到),它的所有static 初始化模块都会运
    行。因此,static 初始化仅发生一次——在Class 对象首次载入的时候。
    (3) 创建一个new Dog()时,Dog 对象的构建进程首先会在内存堆(Heap)里为一个Dog 对象分配足够多的存
    储空间。
    (4) 这种存储空间会清为零,将Dog 中的所有基本类型设为它们的默认值(零用于数字,以及boolean 和
    char 的等价设定)。
    (5) 进行字段定义时发生的所有初始化都会执行。
    (6) 执行构建器。正如第6 章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时
    候。

    五、继承的初始化

     继承初始化时,首先要进行类装载

    public class Insect {
        int i = 9;
        int j;
        Insect() {
        prt("i = " + i + ", j = " + j);
        j = 39;
        }
        static int x1 =
        prt("static Insect.x1 initialized");
        static int prt(String s) {
        System.out.println(s);
        return 47;
        }
    }
    
    public class Beetle extends Insect {
        int k = prt("Beetle.k initialized");
        Beetle() {
            prt("k = " + k);
            prt("j = " + j);
        }
        static int x2 =
                prt("static Beetle.x2 initialized");
        static int prt(String s) {
            System.out.println(s);
            return 63;
        }
        public static void main(String[] args) {
            prt("Beetle constructor");
            Beetle b = new Beetle();
        }
    }
    View Code

    运行结果为:

    static Insect.x1 initialized
    static Beetle.x2 initialized
    Beetle constructor
    i = 9, j = 0
    Beetle.k initialized
    k = 63
    j = 39

    1)发生的第一件事情是装载程序到外面找到那个基础类,若基础类含有另一个基础类,则另一个基础类随即也会载入,以此类推;

    2)接下来,会在根基础类(此时是Insect)执行static 初始化,再在下一个衍生类执行,以此类推

    3)必要的类已全部装载完毕,所以能够创建对象

    4)首先,这个对象中的所有基本数据类型都会设成它们的默认值,而将对象句柄设为null

    5)随后会调用基础类构建器

    6)基础类的构建器完成以后,本类中的实例变量会按本来的顺序得以初始化。最后,执行构建器剩余的主体部分。

    补充:在程序中Insect类中x1后加入final变量

    final int y1 =
    prt("final Insect.y1 initialized");

    则输出的结果是:

    static Insect.x1 initialized
    static Beetle.x2 initialized
    Beetle constructor
    final Insect.y1 initialized }
    i = 9, j = 0}
    Beetle.k initialized
    k = 63
    j = 39 

    可以说明:final变量的初始化本质上是在构造器中进行的

    六、父类构造器---super和this

    super是指子类在调用父类指定参数的构造器

    this表示子类在调用本类中指定参数的另一个构造器

    当子类构造器中没有雨super和this的时候,子类构造器会自动调用父类的无参构造器

    注意:super调用和this调用(super(),this())只能在构造器中使用,且必须是第一行,不能同时使用,最多只能使用一次。

    但是使用super调用父类中的变量和方法时,可以不在第一句

    //Creature 类
    public class Creature {
        {
            System.out.println("Creature非静态初始化代码块");
        }
        public Creature(){
            System.out.println("Creature无参构造函数");
        }
        public Creature(String name){
            System.out.println("Creature有参构造函数name"+name);
        }
    }
    //Animal 类
    public class Animal extends Creature {
        {
            System.out.println("Animal非静态初始化代码块");
        }
        public Animal( String name){ 
            super(name);
            System.out.println("animal无参构造函数");
        }
        public Animal(String name,int age)
        { 
            this(name);
            System.out.println("animal有参构造函数 name"+name+""+age);
        }
    }
    //Fox类
    public class Fox extends Animal {
        {
            System.out.println("fox非静态代码块");
        }
    public Fox(){
        super("饿狼传说",12);
        System.out.println("fox无参构造函数执行");
    }
    public Fox(double weight){
        this();
        System.out.println("fox有参构造函数执行");
    }
    }
    
    //主程序
    public class main {
        public static void main(String[] args) {    
              Fox fox=new Fox(5.6);
        }
    }
    View Code

     运行结果:

    Creature非静态初始化代码块
    Creature有参构造函数name饿狼传说
    Animal非静态初始化代码块
    animal无参构造函数
    animal有参构造函数 name饿狼传说12
    fox非静态代码块
    fox无参构造函数执行
    fox有参构造函数执行

    五、访问子类实例变量

    public class Base {
    
        private int i=2;
        public Base(){
            System.out.println(this.i);//输出值为2
            this.display();     //输出值为2
        }
        public void display(){
            System.out.println(i);
        }
    }
    
    //son类
    public class Son extends Base {
        private int i=22;
        public Son(){
            System.out.println("son中的变量i:"+this.i); //输出值为22
            i=222;
        }
        public void diplay(){
            System.out.println(i);
        }
    }
    //主程序
    public class main {
        public static void main(String[] args) {
                new Son();
        }
    }
    
    运行结果为:
    2
    2
    son中的变量i:22
    View Code
  • 相关阅读:
    ArcGIS API for Python
    ArcGIS Engine二次开发:从入门到精通
    OAuth2.0是什么?
    ArcGIS如何使用ArcToolbox新建要素类
    后端如何返回json
    Flask框架和Django框架
    ArcGIS时间——ArcToolbox
    ArcGIS时区设置2-编辑器追踪属性
    使用ABAP代码生成二维码(QR Code)
    如何自行分析SAP WebClient UI开发环境里抛出的错误消息根源
  • 原文地址:https://www.cnblogs.com/abc8023/p/4231003.html
Copyright © 2011-2022 走看看