10. public class Foo {
11. public int a;
12. public Foo() { a = 3; }
13. public void addFive() { a += 5; }
14. }
and:
20. public class Bar extends Foo {
21. public int a;
22. public Bar() { a = 8; }
23. public void addFive() { this.a +=5; }
24. }
invoked with:
30. Foo foo = new Bar();
31. foo.addFive();
32. System.out.println(”Value: “+ foo.a);
What is the result?
A. Value: 3
B. Value: 8
C. Value: 13
D. Compilation fails.
E. The code runs with no output.
F. An exception is thrown at runtime.
Answer: A答案是A,为什么不是13呢????
11. public int a;
12. public Foo() { a = 3; }
13. public void addFive() { a += 5; }
14. }
and:
20. public class Bar extends Foo {
21. public int a;
22. public Bar() { a = 8; }
23. public void addFive() { this.a +=5; }
24. }
invoked with:
30. Foo foo = new Bar();
31. foo.addFive();
32. System.out.println(”Value: “+ foo.a);
What is the result?
A. Value: 3
B. Value: 8
C. Value: 13
D. Compilation fails.
E. The code runs with no output.
F. An exception is thrown at runtime.
Answer: A答案是A,为什么不是13呢????
2. protected int blipvert(int x) { return 0; }
3. }
4. class Vert extends Blip {
5. // insert code here
6. }
Which five methods, inserted independently at line 5, will compile?
(Choose five.)
A. public int blipvert(int x) { return 0; }
B. private int blipvert(int x) { return 0; }
C. private int blipvert(long x) { return 0; }
D. protected long blipvert(int x) { return 0; }
E. protected int blipvert(long x) { return 0; }
F. protected long blipvert(long x) { return 0; }
G. protected long blipvert(int x, int y) { return 0; }
Answer: ACEFG顺便讲一下这道题
32. System.out.println(”Value: “+ foo.a);打印的就是父类Foo的属性a。
但是30行构造出来的foo是子类Bar()的啊,他的属性应该a = 8????
foo是Foo类型引用,它会取Foo类的a
这个问题和这个大概差不多,类的属性是不存在多态性的。
foo.a是父类对象的属性,foo.addFive()多态调用子类的方法因为foo引用的是一个子类实例构造对象,子类方法addFive()覆盖父类的addFive()方法。
我想打给就是这么的吧,不知道正确否。
我不明白这个。有没有人可以给予解释下下啦。。
在我看来本应该是可以的呢。最起码也最简单地理解得到这样看起来确实是比基类的大了呀?不明白。
D选项错误~·是指返回类型long和int不同,所以报错吗???
如果把参数类型换一下的话~~比如E,F选项编译器就不会认为是重写父类的方法吗??
哪个类型引用它的属性就是哪个类型的吗??
比如B继承A的话,A b = new B();这里实例b的属性是A的,方法是B的,这样说对吗???
F返回也是long,但是它的参数变了,这样编译器是不是就不认为是方法的重写了???
等号左边你是把foo 声明为Foo类型,如果右边是定义一个Foo类的实例的话,那么你那么是把这个实例的引用赋给了foo,所以foo引用变量引用的foo.a将会是Foo实例中的变量a ,即a=3,而方法addFive()也是Foo中定义的方法,
如果等号右边是定义一个Boo类的实例的话,那么你是把这个BOO实例的引用给了foo,这个时候foo引用变量引用的方法将会是Boo中的addFive()(addFive()中的a,也是Boo中的定义的a,用这方法得到a 的结果也是13,)但是foo引用的变量a就仍是Foo中定义的变量a,foo.a就是FOO中的a=3;
一名句话,经多态中,变量是不可以实替换的,方法才可以,
若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法D. 如果是long则在编译时,会提示重写了父类的方法,但是返回类型不匹配
class Foo {
public int a;
public Foo()
{ a = 3; }
public void addFive()
{ a += 5; } }
class Bar extends Foo {
public int a;
public Bar()
{ a = 8; }
public void addFive()
{ this.a +=5; } }
public class Test2{
public static void main(String[] args){
//Foo foo = new Bar();
Foo foo =new Foo();
Bar bar=new Bar();
System.out.println("Value: "+foo.a); //3
System.out.println("Value: "+bar.a); //8
foo=bar;
System.out.println("Value: "+foo.a); //3
System.out.println("Value: "+bar.a); //8
foo.addFive();
System.out.println("Value: "+foo.a); //3
System.out.println("Value: "+bar.a); //13
}
}
结果:c:\J>java Test2
Value: 3
Value: 8
Value: 3
Value: 8
Value: 3
Value: 13楼主明白了吧?父类属性是不被改变的,多态的重写只对方法而言。
System.out.println("Value: "+foo.a);之所以会输出3是因为你创建
子类对象的时候会调用你的父类的默认的构造函数,把父类的属性a赋值为3(你的a的属性是public),
当你调用父类foo.a时输出是3。
class Foo {
public int a;
public Foo(){
a = 3;
}
public int addFive(){
return a += 5;
} }
class Bar extends Foo {
public int a;
public Bar(){
a = 8;
}
public int addFive(){
return this.a +=5;
} }
public class ClassVar{
public static void main(String[] args){
Foo foo=new Bar();
System.out.println(foo.a);
//foo.addFive();
System.out.println(foo.addFive());
}
}这样就是13了,因为参数是值传递,并不改变传入的值
而实例变量却不会有这样的机制,他只能够找到父类中定义的变量
我想问一下Foo foo=new Bar()这样创建出来的实例foo它的属性a是3还是8呢???
重写的原则:
首先,继承是重写的前提!
1.方法签名必须相同(包括:方法名,参数个数,参数类型,参数顺序)
2.方法的返回相同(可以不同,但要支持多态就要相同)
3.访问权限不能比父类小(大于等于)
4.抛出异常不能比父类大1. public class Blip {
2. protected int blipvert(int x) { return 0; }
3. }
4. class Vert extends Blip {
5. // insert code here
6. }
Which five methods, inserted independently at line 5, will compile?
(Choose five.)
A. public int blipvert(int x) { return 0; } //这个是重写 public 的权限大于protected。没有任何问题 对
B. private int blipvert(int x) { return 0; } //权限变小 错
C. private int blipvert(long x) { return 0; } //参数类型不一样,是子类的一个新方法 对
D. protected long blipvert(int x) { return 0; } // 返回类型不一样 错
E. protected int blipvert(long x) { return 0; }//参数类型不一样,是子类的一个新方法 对
F. protected long blipvert(long x) { return 0; }//参数和返回类型不一样,是子类的一个新方法 对
G. protected long blipvert(int x, int y) { return 0; //参数不一样 对
跟你拆开说:
Foo foo; //在栈中创建一个Foo变量
new Bar();//在堆中创建一个Bar类型对象,当然创建子类对象时先要创建父类的对象。所以在堆内存中是有两个对象的:一个是Bar的,一个是Foo的。 Bar中有一个a=8;Foo中有一个 a=3; 在编译时编译器只知道foo是Foo对像,他不知道他实际上指向了Bar对象。在编写的时候也只能.出Foo类中定义的成员。但在运行时,让foo指向了Bar的对象。这样就实现了类多态(父类变量指向子类对象)。这样在执行下面的方法时,他会先找方法表看子类对象对方法进行重写没有,如果有就调用子类重写后的方法。 而属性是没有这样的机制的,所以对于他来说他只知道堆内存中Foo的对象a,而不是去寻找Bar中对象的a
public int a=1;
}public class B
extends A{
public int a = 2;
public int b = 3;
}A obj = new B();
System.out.println(obj.a); //输出1//System.out.println(obj.b);//ERROR!因为在编译时,编译器并不知道a在运行时指向B的对象,所以这样会编译出错。其实如果是在运行时,这句话一点问题都没有Sytem.out.println(((B)obj).a);//输出2 其实obj本来就是指向B对象的,所以他实质上是个B类型。 把obj强制转换成真正属于自己的B类型时,他就可以访问到B里定义的a了
32. System.out.println(”Value: “+ foo.a);改成32. System.out.println(”Value: “+ (Bar)foo.a); 这样就能输出你要的13了
addFive()方法已经被子类重写了,所以foo.addFive()执行的是已经重写后的方法,此时执行addFive()方法的是Bar中的a,然而最后显示出来的是Foo中的属性a,我这样理解对不??
public int a;
public Foo() { a = 3; }
public void addFive() { a += 5; }
}
class Bar extends Foo {
public int a;
public Bar() { a = 8; }
// public void addFive() { this.a +=5; } //不重写addFive()方法
}
public class Test1 {
public static void main(String[]args){
Foo f=new Bar();
f.addFive();
System.out.println(f.a);//输出8
}
父类中的所有属性都被子类继承下来,所有说Bar中有两个a,一个是父类的,一个是子类的,当Foo f=new Bar()时候,先调用父类的构造方法,所以Bar中的一个a(继承父类的a)变成了3,再调用子类自己的构造方法子类中的自己定义的a变成了8;这个时候调用f.addFive()时,由于子类的addFive()对父类的该方法进行了重写,所以就调用子类中的addFive()方法,此时Bar中自己定义的a为13.当没有重写的时候,改变的就是父类的a,父类的属性也就改变了!
对这两句话的理解是Foo f=new Bar();f.a;
当你向上转型的时候,Foo类型的Bar对象f只能看见Foo类型中的东西,并不能访问Bar中自己定义的成员变量,所以f.a调用的是基类的对象a,也就是子类从父类继承下来的a,不是自己定义的a!
没错就是这样CSDN上的朋友都是助人为乐的!即便你没分,论坛上的朋友也会帮助你的! 在帮助别人中巩固和提升自己的知识楼主看来是在准备SCJP考试啊。我也要考的
Foo f=new Bar();
f.addFive();//此时调用的子类的方法
System.out.println(f.a);//此时是调用父类的属性,父类的属性并没有改变,所以输出为3 Thingking in Java中有一段话可以很好的解释:
对于属性和静态方法来说,调用取决于声明的类型,而对于其他的取决于运行时的类型,这里Foo是声明类型,Bar则是运行时的类型。第二题:
应该是一个方法重写的问题:对于方法重写有一些限制:
如果编译器认为是方法的重写的话,就会做一些限制,必须有相同的方法名,参数列表,和返回值,而其访问的可见度不能减小。