• Java访问子类对象的实例变量


    对于Java这种语言来说,一般来说,子类可以调用父类中的非private变量,但在一些特殊情况下,

    Java语言可以通过父类调用子类的变量

    具体的还是请按下面的例子吧!

    package com.yonyou.test;
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-2
     */
    
    class Base
    {
    	// 定义了一个名为i的实例变量
    	private int i = 2;
    	public Base()
    	{
    		this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象
    	}
    	public void display()
    	{
    		System.out.println(i);
    	}
    }
    // 继承Base的Derived子类
    class Derived extends Base
    {
    	// 定义了一个名为i的实例变量
    	private int i = 22;
    	// 构造器,将实例变量i初始化为222
    	public Derived()
    	{
    		i = 222;              //②
    	}
    	public void display()
    	{
    		System.out.println(i);
    	}
    }
    public class Test
    {
    	public static void main(String[] args)
    	{
    		// 创建Derived的构造器创建实例
    		new Derived();       //①
    	}
    }
    	  
    

      最后的结果是多少呢?没错就是0,是不是很意外,这里你需要明白。

    public Base()
     {
     this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象
     }
    

      这里面的this指的是当前正在运行的那个对象,那么当前运行的对象是谁?没错,就是Derived对象。

         为了确定是Derived,我们可以看下面的代码:

        

    	public Base()
    	{ 
    		System.out.println(this.i); //新增加的变量 其值为2
    		this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象
    		System.out.println(this.getClass());
    	}
    
         //最后结果为:
    // 2 // 0 // class com.yonyou.test.Derived

      

         但是现在的问题又出现了如果修改上面的代码加入System.out.println(this.i)

         如下面的例子:

    public Base()
    	{ 
    		System.out.println(this.i); //新增加的变量 其值为2
    		this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象
    	}
    

      既然这俩this的指的是Derived对象,那为什么其值不是0,而是父类Base对象里面对应变量

         的值2呢?

         这里涉及到了编译类型和运行时类型相关的内容。当变量的编译类型和运行时类型不同的话,通过该对象访问其所引用对象的实例变量的时候

         表现出该实例变量所声明时的类型决定。因为

          System.out.println(this.i); //新增加的变量 其值为2

         这里的this访问的变量,所以其值为声明它的对象Base的值,即2

         但通过通过此实例变量调用它所对应的实例方法的时候,该方法的行为将由它实际所引用的对象来决定。

         因为

         this.display(); //注意这里面的this代表当前正在运行的对象,即Derived对象

         这里的this的实际引用它的对象为Derived,所以其i值为0.

         根据java创建对象时初始化对象的时机(http://www.cnblogs.com/xiohao/p/4349833.html),我们知道这时Derived中的变量i还没有初始化,

         所以最后的结果为:0

         最后提示一下如果是静态方法的话,仅仅序声明它的类型相关,与其它的没有任何关系哦...

        下面是对比的例子:

        1 静态方法,仅仅与其声明的类型有关

         

    package com.yonyou.test;
    
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-20
     */
    
    
    public class Test
     { 
    	public static void main(String[] args) {
                   Base b=new Base();
                   Base  c=new Inherit();
                   b.a();
                   b.b();
                   c.a();
                   c.b();
        }
    	}
    	class Base{
            static void a( ){System.out.println("A");  }
                     void b( ){System.out.println("B"); }
    }
     class  Inherit extends Base{
              static void a( ){System.out.println("C");  }
                      void b( ){System.out.println("D"); }
            
    }
    

     最后的结果为:A,B,A,D  

    2.非静态方法正常,与其真正所引用的类型相关

         

    package com.yonyou.test;
    
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-20
     */
    
    
    public class Test
     { 
    	public static void main(String[] args) {
                   Base b=new Base();
                   Base  c=new Inherit();
                   b.a();
                   b.b();
                   c.a();
                   c.b();
        }
    	}
    	class Base{
             void a( ){System.out.println("A");  }
                     void b( ){System.out.println("B"); }
    }
     class  Inherit extends Base{
               void a( ){System.out.println("C");  }
                      void b( ){System.out.println("D"); }
            
    }
    

      结果为:A,B,C,D

       

         上面的话有一些绕,请务必多读几遍,反复揣摩,这样你会更上一层楼。

         如果实在不懂也可以发送邮件至:12612455595@qq.com

         如果你确实理解了的话,请通过下面的例子测试一下:

        

    package com.yonyou.test;
    
    
    
    /**
     * 测试类
     * @author 小浩
     * @创建日期 2015-3-2
     */
    
    class Animal
    {
    	// desc实例变量保存对象toString方法的返回值
    	private String desc;
    	public Animal()
    	{
    		// 调用getDesc()方法初始化desc实例变量
    		this.desc = getDesc();            //②
    	}
    	public String getDesc()
    	{
    		return "Animal";
    	}
    	public String toString()
    	{
    		return desc;
    	}
    }
    public class Wolf extends Animal
    {
    	// 定义name、weight两个实例变量
    	private String name;
    	private double weight;
    	public Wolf(String name , double weight)
    	{
    		// 为name、weight两个实例变量赋值
    		this.name = name;                 //③
    		this.weight = weight;
    	}
    	// 重写父类的getDesc()方法
    	@Override
    	public String getDesc()
    	{
    		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]

        测试例子2:

       

    class Base
    {
    	int count = 2;
    	public void display()
    	{
    		System.out.println(this.count);
    	}
    }
    class Derived extends Base
    {
    	int count = 20;
    	@Override
    	public void display()
    	{
    		System.out.println(this.count);
    	}
    }
    public class FieldAndMethodTest
    {
    	public static void main(String[] args)
    	{
    		// 声明、创建一个Base对象
    		Base b = new Base();             //①
    		// 直接访问count实例变量和通过display访问count实例变量
    		System.out.println(b.count);
    		b.display();
    		// 声明、并创建一个Derived对象
    		Derived d = new Derived();       //②
    		// 直接访问count实例变量和通过display访问count实例变量
    		System.out.println(d.count);
    		d.display();
    		// 声明一个Base变量,并将Derived对象赋给该变量
    		Base bd = new Derived();         //③
    		// 直接访问count实例变量和通过display访问count实例变量
    		System.out.println(bd.count);
    		bd.display();
    		// 让d2b变量指向原d变量所指向的Dervied对象
    		Base d2b = d;                    //④
    		// 访问d2b所指对象的count实例变量
    		System.out.println(d2b.count);
    	}
    }
    

      运行结果为:

        

    2
    2
    20
    20
    2
    20
    2
    

      

         好吧,今天就先到这里吧、、、

  • 相关阅读:
    mysql 主从架构搭建
    tomcat+nginx 反向代理 动静分离
    ELK(Elasticsearch + Logstash + Kibana)安装部署对nginx的日志收集
    Kibana server is not ready yet出现的原因
    apache+tomcat+单机双实例+动静分离+负载均衡
    docker的基本安装和简单使用+Dockerfile常用指令
    LVS+keepalived+DR 负载均衡高可用
    md5sum摘要
    python爬虫
    python和数据库
  • 原文地址:https://www.cnblogs.com/xiohao/p/4349964.html
Copyright © 2020-2023  润新知