[ Java学习 ] 一道Java好题的详细题解 001

  之所以贴出这道题,是因为觉得真的好,真的值得整理总结,因为它覆盖了Java的许多语法知识点,可以说,只要有一点没有透彻弄懂,这题就很难做到全对

 

  有这样的血泪教训,是因为,我在还没完全彻彻底底明白所有语法点之前,我凭着感觉做时,做了3次,都和答案不一样。于是决定好好把知识点理一理,帮助自己日后复习,也希望给初学者一些帮助~

 

-------------------------------其他相关文章------------------------------

 [Java学习 ] 类的其他文章汇总(都是超链接,可直接点击):

[ Java学习 ] 实验 银行业务模拟

[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 001

[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 002

[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 003

[ Java学习 ] 包语句 package等语句的汇总整理

[ Java学习 ] Java变量以及内存分配(非常重要)

[ Java学习 ] 其他知识总结(重要)

[ Java学习 ] “goto语句“ 和 “continue + 标号” 的不同待遇

[ Java学习 ] toString方法 和 equals方法

 

 

[ Java学习 ] 查阅资料整理 001

[ Java学习 ] 查阅资料整理 002

 

-------------------------------言归正传,进入本文的内容-------------------------------

先上题目,题目是一段Java代码,要求我们写出它的输出

(先别急着在eclipse上跑程序,先自己把答案写答案出来

因为…如果你对知识点不是特别烂熟于心,你自己第一次做的答案,很可能会错很多,就像我一样)


//题目是一段Java代码,要求我们写出它的输出结果
class A
{
	int a = 10;
	static int b = 20;
	A()
	{
		
	}
	void f1()
	{
		System.out.println("A.a=" + a++);
	}
	static void f2()
	{
		System.out.println("A.b=" + b++);
	}
}


public class test extends A
{
	int a = 100;
	static int b = 200;
	void f1()
	{
		System.out.println("test.a=" + a++);
	}
	static void f2()
	{
		System.out.println("test.b=" + b++);
	}
	public static void main(String args[])
	{
		A t= new test();
		t.f1();
		t.f2();
		System.out.println("a=" + t.a);
		System.out.println("b=" + t.b);
		test s = new test();
		System.out.println("a=" + s.a);
		System.out.println("b=" + s.b);
	}
}



//我们先把最后三句代码屏蔽掉,先只看上转型变量的部分,待会再来单独分析最后三句的输出
//我的这个程序可以在eclipse上跑一下,因为我加了很多注释,来说明每步的结果,为什么会是那样
package test;

class A
{
	int a = 10;
	static int b = 20;
	A()
	{
		System.out.println("a=" + a + ", b=" + b);
		System.out.println("加上这句,可以很清楚地看出,初始化了A类以后,才调用A的构造函数");
		System.out.println("略微提一下,初始化的意思是,调用 int a = 10; 和 static int b = 20; 这两句代码");
	}
	void f1()
	{
		System.out.println("A.a=" + a++);
	}
	static void f2()
	{
		System.out.println("A.b=" + b++);
		System.out.println("上句代码的输出,体现的知识点是:");
		System.out.println("如果子类重写了父类静态方法,那么子类对象的上转型对象,不能调用子类的静态方法,只能调用父类的静态方法。");
	}
	void printABNow()
	{
		System.out.println("a=" + a + ", b=" + b);
	}
}


public class test extends A
{
	int a = 100;
	static int b = 200;
	test()
	{
		System.out.println("a=" + a + ", b=" + b);
		System.out.println("加上这句,可以很清楚地看出,初始化了test类以后,才调用test的构造函数");
		System.out.println("并且我们还发现,a和b的值都和之前不一样了");
		
		System.out.println();
		System.out.println("这时你可能会猜测说,是不是a和b的值被覆盖了,但其实没有覆盖,只是父类中的a和b,被子类中的a和b隐藏了而已。");
		System.out.println("并且,父类中的a和b,仍然还可以通过,调用从父类继承的方法,操作隐藏的成员变量,我们可以来做个测试");
		printABNow();
		System.out.println("这个测试告诉我们,其实 100 和 200,分别只是test类的a和b,而 A类中的a和b,还是仍然保留着,并且能通过A调用A类的函数来观察");
		System.out.println();
		
	}
	void f1()
	{
		System.out.println("test.a=" + a++);
		System.out.println("上句代码的输出,体现的知识点是:");
		System.out.println("如果子类重写了父类的某个实例方法后,当对象的上转型调用这个实例方法时,一定是调用了子类重写的实例方法。");
	}
	static void f2()
	{
		System.out.println("test.b=" + b++);
	}
	public static void main(String args[])
	{
		A t= new test();
		t.f1();
		t.f2();
		System.out.println("a=" + t.a);
		System.out.println("b=" + t.b);
		System.out.println("上两句不是调用方法,而是输出类中的值,它体现的知识点是:");
		System.out.println("可以通过上转型变量访问父类中被子类隐藏的成员变量。");
		System.out.println("这是因为上转型变量通过父类模板去寻找相应的成员变量,找到的正是父类中被子类隐藏的成员变量。");
		System.out.println("不过需要注意一下的是,之前调用函数时,是有后++自增符号的,所以值发生了小变化");
//		test s = new test();
//		System.out.println("a=" + s.a);
//		System.out.println("b=" + s.b);
	}
}
//在eclipse上跑完得到的结果是:
a=10, b=20
加上这句,可以很清楚地看出,初始化了A类以后,才调用A的构造函数
略微提一下,初始化的意思是,调用 int a = 10; 和 static int b = 20; 这两句代码
a=100, b=200
加上这句,可以很清楚地看出,初始化了test类以后,才调用test的构造函数
并且我们还发现,a和b的值都和之前不一样了

这时你可能会猜测说,是不是a和b的值被覆盖了,但其实没有覆盖,只是父类中的a和b,被子类中的a和b隐藏了而已。
并且,父类中的a和b,仍然还可以通过,调用从父类继承的方法,操作隐藏的成员变量,我们可以来做个测试
a=10, b=20
这个测试告诉我们,其实 100 和 200,分别只是test类的a和b,而 A类中的a和b,还是仍然保留着,并且能通过A调用A类的函数来观察

test.a=100
上句代码的输出,体现的知识点是:
如果子类重写了父类的某个实例方法后,当对象的上转型调用这个实例方法时,一定是调用了子类重写的实例方法。
A.b=20
上句代码的输出,体现的知识点是:
如果子类重写了父类静态方法,那么子类对象的上转型对象,不能调用子类的静态方法,只能调用父类的静态方法。
a=10
b=21
上两句不是调用方法,而是输出类中的值,它体现的知识点是:
可以通过上转型变量访问父类中被子类隐藏的成员变量。
这是因为上转型变量通过父类模板去寻找相应的成员变量,找到的正是父类中被子类隐藏的成员变量。
不过需要注意一下的是,之前调用函数时,是有后++自增符号的,所以值发生了小变化


//再来分析刚刚屏蔽掉的最后3句代码
package test;
class A
{
	int a = 10;
	static int b = 20;
	A()
	{
		
	}
	void f1()
	{
		System.out.println("A.a=" + a++);
	}
	static void f2()
	{
		System.out.println("A.b=" + b++);
	}
}


public class test extends A
{
	int a = 100;
	static int b = 200;
	void f1()
	{
		System.out.println("test.a=" + a++);
	}
	static void f2()
	{
		System.out.println("test.b=" + b++);
	}
	public static void main(String args[])
	{
//		A t= new test();
//		t.f1();
//		t.f2();
//		System.out.println("a=" + t.a);
//		System.out.println("b=" + t.b);
		test s = new test();
		System.out.println("a=" + s.a);
		System.out.println("b=" + s.b);
		System.out.println("上面两句代码的输出,体现的知识点是:");
		System.out.println("在Java中,子类也可以隐藏由父类继承来的成员变量,只要子类中声明的成员变量和父类的成员变量同名,就可以将其隐藏。 ");
	}
}

//在eclipse上跑完得到的结果是:
a=100
b=200
上面两句代码的输出,体现的知识点是:
在Java中,子类也可以隐藏由父类继承来的成员变量,只要子类中声明的成员变量和父类的成员变量同名,就可以将其隐藏。 


最后,再把我查阅过的资料一并附上:(都是超链接,可直接点击):

Java子类继承(二):隐藏成员变量和方法重写的理解

Java子类继承(二):隐藏成员变量和方法重写的理解

 

最后的最后,我想附带说一下的就是,这题主要是难在上转型变量的部分,因为语法规则比较多,稍不注意就很可能弄错,至于普通的继承,其实和C++大同小异。

 

所以,我个人的感觉是,学习Java的继承时,有必要把上转型变量的语法透彻清楚地弄得明明白白,因为…

 

上转型变量真的是稍不注意就能踩肯多坑的知识点啊

^(* ̄(oo) ̄)^










转载于:https://www.cnblogs.com/mofushaohua/p/7789360.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、判断题(每题1分,共15分) 1、Java允许创建不规则数组,即Java多维数组中各行的列数可以不同。 ( ) 2、接口和类一样也可以有继承关系,而且都只能支持单继承。 ( ) 3、所有类至少有一个构造器,构造器用来初始化类的新对象,构造器与类同名,返回类型只能为void。 ( ) 4、包是按照目录、子目录存放的,可以在程序中用package定义包,若没有package一行,则表示该文件中的类不属于任何一个包。 ( ) 5、Java对事件的处理是采用委托方式进行的,即将需要进行事件处理的组件委托给指定的事件处理器进行处理。 ( ) 6、在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在前面,子类放在后面。 ( ) ..... 二、单项选择题(每题2分,共30分) 1、若在某一个类定义中定义有如下的方法: final void aFinalFunction( );则该方法属于( )。 A、本地方法 B、解态方法 C、最终方法 D、抽象方法 2、main方法是Java Application程序执行的入口点,关于main方法的方法头以下哪项是合法的( )。 A、 public static void main() B、 public static void main(String[ ] args) C、 public static int main(String[ ] args) D、 public void main(String arg[ ]) 3、在Java中,一个类可同时定义许多同名的..... ...... 14、一个线程的run方法包含以下语句,假定线程没有被打断,以下哪项是正确的( ) 1.try{ 2. sleep(100); 3. }catch(InterruptedException e){ } A、不能通过编译,因为在run方法中可能不会捕捉到异常。 B、在第2行,线程将暂停运行,正好在100毫秒后继续运行。 C、在第2行,线程将暂停运行,最多在100毫秒内将继续运行。 D、在第2行,线程将暂停运行,将在100毫秒后的某一时刻继续运行。 15、以下哪个接口的定义是正确的?( ) A、 interface A { void print() { } ;} B、 abstract interface A { void print() ;} C、 abstract interface A extends I1, I2 //I1、I2为已定义的接口 { abstract void print(){ };} D、 interface A { void print();} 三、程序阅读题(1~8题每题4分,第9题占8分,共40分) 1、若文件test.dat不存在,则试图编译并运行以下程序时会发生什么情况? import java.io.*; class TestIO { public static void main(String[] args) { try{ RandomAccessFile raf=new RandomAccessFile("test.dat","r"); int i=raf.readInt(); } catch(IOException e){System.out.println("IO Exception"); } } } 2、以下程序的输出结果为 。 public class EqualsMethod { public static void main(String[] args) { Integer n1 = new Integer(12); Integer n2 = new Integer(12); System.out.print(n1= =n2); System.out.print(“,”); System.out.println(n1! =n2); } } ........ 1、在java中如果声明一个类为final,表示什么意思? 答:final是最终的意思,final可用于定义变量、方法和类但含义不同,声明为final的类不能被继承。 2、父类的构造方法是否可以被子类覆盖(重写)? 答:父类的构造方法不可以被子类覆盖,因为父类和子类的类名是不可能一样的。 3、请讲述String 和StringBuffer的区别。 答:String 类所定义的对象是用于存放“长度固定”的字符串。 StringBuffer类所定义的对象是用于存放“长度可变动”的字符串。 4、如果有两个类A、B(注意不是接口),你想同时使用这两个类的功能,那么你会如何编写这个C类呢? ........

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值