• Java初始化顺序


    实例变量的实例化

    三个地方:

    1. 定义实例变量指定初始值
    2. 非静态初始化块中对实例变量指定初始值
    3. 构造器中对实例变量指定初始值

    其中,1、2中方式比第三种方式更早执行,1、2种执行顺序与它们在源程序中的排列顺序相同。

    类变量的初始化

    两个地方:

    1. 定义是指定
    2. 静态初始化块中指定

    这两种方式的执行顺序与它们在源程序中的排列顺序相同

    public class StaticInitTest {
    
        static int count = 2;
        
        static {
            System.out.println("StaticInitTest静态初始化块");
            name = "Java编程";
        }
        
        static String name = "疯狂java讲义";
        
        public static void main(String[] args) {
            
            System.out.println("count类变量的值:" + StaticInitTest.count);
            System.out.println("name类变量的值:" + StaticInitTest.name);
        }
    }

    输出:

    StaticInitTest静态初始化块

    count类变量的值:2

    name类变量的值:疯狂java讲义

    解析:name刚开始赋值为Java编程

    从内存看Java实例化

    class Price {
    
        final  static Price INSTANCE = new Price(2.8);
        
        static double initPrice = 20;
        
        double currentPrice;
        public Price(double discount){
            
            currentPrice = initPrice - discount;
        }
        
    }
    
    public class PriceTest{
        
        public static void main(String[] args) {
            
            System.out.println(Price.INSTANCE.currentPrice);
            
            Price p = new Price(2.8);
            
            System.out.println(p.currentPrice);
        }
    }

    输出:-2.8

    17.2

    解析:

    初始化分为以下两个阶段:

    1.  系统为Price的两个类变量分配内存空间

    2.  按初始化代码的排列顺序执行初始化

    Java初始化的内存分配

    (注意java在继承变量和方法的时候是有区别的)

    当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法的行为将由它实际所引用的对象来决定。

    原因:Java编译器会将父类的方法加到子类中去,而父类中的实例变量则不会。

    结论:当一个程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为其父类中定义的所有实例变量分配内存。

    public class Test {
    
        public static void main(String[] args) {
            
            new Derived();
        }
    }
    
    class Base{
        
        private int i = 2;
    
        public Base(){
    
            //要弄清楚这里的this指向的是子类
            //可以通过this.getClass开看
            //所以this.display()调用的是子类的,输出的i当然就是子类的i了
            this.display();
        }
        
        public void display(){
            System.out.println(i);
        }
    }
    
    class Derived extends Base{
        
        private int i = 22;
        
        public Derived(){
            i = 222;
        }
        
        public void display(){
            System.out.println(i);
        }
    }
    
    输出:0
    例子2:
    class Animal{
        
        private String desc;
        public Animal(){
            this.desc = getDesc();
        }
        
        public String getDesc(){
        
            System.out.println("Animal");
            return "Animal";
        }
    }
    public class Wolf extends Animal{
    
        private String name;
        private double weight;
        
        public Wolf(String name, double weight){
            
            this.name = name;
            this.weight = weight;
        }
        
        @Override
        public String getDesc(){
            
            System.out.println("Wolf[name=" + name + " ,weight=" + weight +"]");
            return "Wolf[name=" + name + " ,weight=" + weight +"]";
        }
        
        public static void main(String[] args) {
            
            System.out.println(new Wolf("灰太狼", 32.3));
        }
    }

    输出:Wolf[name=null ,weight=0.0]

    javaSyntax.Wolf@770848b9

    解析:因为子类重写了父类的方法,所以实例化子类实例时,不会把父类的那个方法复制过来,所以getDesc()调用的是子类的重写方法

    例子3:

    class Fruit{
        
        String color = "未确定颜色";
        
        public Fruit getThis(){
            
            return this;
        }
        
        public void info(){
            
            System.out.println("Fruit 方法");
        }
    }
    
    
    
    public class Apple extends Fruit{
    
        @Override
        public void info(){
            
            System.out.println("Apple 方法");
        }
        
        //通过super调用父类的info()方法
        public void AccessSuperInfo(){
            
            super.info();
        }
        
        //尝试返回super关键子代表的内容
        public Fruit getSuper(){
            
            return super.getThis();
        }
        
        String color = "红色 ";
        
        public static void main(String[] args) {
            
            Apple a = new Apple();
            Fruit f = a.getSuper();
            
            System.out.println("a和f所引用的对象是否相同:" + (a == f));
            System.out.println("访问a所引用对象的color实例变量: " + a.color);
            System.out.println("访问f所引用对象的color实例变量:" + f.color);
            
            a.info();
            f.info();
            
            //调用AccessSuperInfo来调用父类的info()方法
            a.AccessSuperInfo();
            
        }
    }
  • 相关阅读:
    迷宫广搜
    通过地址获取百度地图经纬度
    图片上传存储数据库
    spring boot加载配置文件的顺序
    阿里 短信认证
    spring boot properties文件与yaml文件的区别
    springboot pom问题及注解
    手机短信认证
    获取class对象的三种方法以及通过Class对象获取某个类中变量,方法,访问成员
    关于mysql优化问题
  • 原文地址:https://www.cnblogs.com/mynona/p/3607876.html
Copyright © 2020-2023  润新知