子类和父类的转换!谢谢!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了子类和父类的转换!谢谢!相关的知识,希望对你有一定的参考价值。
class A
int name=3;
int area()
System.out.println("A");
return 1;
class C extends A
int name=4;
int area()
System.out.println("C类方法");
return 1;
public static void main(String[]args)
A a = new C();
a.area();
System.out.println(a.name);
输出结果为
c类方法
3
我不明白,实际上创建的是子类的实例,为什么调用的是子类的方法,父类的成员变量?
如果说,因为子类重写了父类的方法,那还可以理解,可是为什么成员变量name会是父类的值3?而不是子类的值4?
那么我就C c=new C();
System.out.println(c.name); 输出的是竟然是4
C c ,A a,只是一个存放地址的指针。实际的对象都是 子类C啊,那么name的值都应该是4不是吗?为什么会出现不同的结果?
还有,当我把A类的area()方法删除,也就是只有子类有area()这个方法,重新编译,结果出现了错误,根本访问不到area()这个方法。实际创建的对象是子类,子类当然可以访问area这个方法,怎么会出现了错误呢? 网上搜搜说必须强制转换成子类才可以访问子类的方法,我不清楚怎么回事。
子类和父类的转换,我不明白这究竟有什么转换啊,还是 A a有什么其他的意思?
我还不清楚 父类强制转换成子类 怎么转,这个教程好像网上的也少,希望大家帮帮啊!
万分感谢!
java 的子类和父类的转换
然后是a.name=3这个问题,这是由于直接访问成员变量的话 指针指向的任然是父类成员变量,这点记住就行,实际中一般都设getName()、setName()方法进行访问和设置,把name设为private,这样才符合面向对象封装特性,你可以试一下,a.getName()的结果肯定是4
另外父类转化为子类的问题,父类转化为子类不是一定可行的,父类要想转化为子类,其指向的内存块的内容一定要大于等于子类,(即指向对象一定要是子类或者子类的子类。。。)
比如:
A a = new C();
此时把a强制转换为子类是正确的
而A a = new A();
此时把a强制转换为子类则会出错
希望对你有帮助,有不明白的地方可以再问我追问
另外我想问下,在父类有一个抽象方法。
public abstract double calcArea();
然后我在子类重写他,
public float calcArea()
为什么这样也可以?不是说你重写一个方法,返回值必须要一模一样吗,为什么呢?
难道说仅仅只是抽象的可以?
那我声明普通 double calcArea(),重写的时候可以float calcArea() 吗?
首先A a = new C();这条语句利用了java中的多态特性,即子类对象可以当做父类对象来看。
但是,若我们把子类对象当做父类对象来看是,那么就只能访问父类已有定义的属性和方法,不能访问子类扩展的属性和方法。要是子类把父类的方法覆盖了,再把子类对象的当做父类对象来看,去调用方法,调用的是覆盖后的方法(子类中定义的方法)。
还有就是关于name=3的问题。要记住java中只有在普通的方法中才能表现出多态特性,变量是没有多态存在的,所以是不会输出name = 4.
至于类的转换:
引用类型转换(是引用变量的类型的转换!)
1 向下转型(自动类型转换),是小类型到大类型的转换
如:
Circle c = new Circle(1,2,3);
Shape s = c;//表示圆一定是图形
2 向上造型(强制类型转换),是大类型到小类型。
如:
Shape s = new Circle(1,2,3);
Cirlcle c = (Circle)s; //当s实际引用圆时候,能够转换成功
s = new Rectangle(1,1,2,2);
Circle c2 = (Circle) s;//出现类型转换异常,因为
// s引用的是Rectangle 不是圆实例。
3 instanceof 运算符,用来检查引用对象的类型。
经常与“引用类型强制转换”配合,实现安全的类型换,
避免类型转换异常。
如你例子中的就是向下转型,也就是多态,若果要父类转成子类,就是向上转型,这要 承担出异常的后果,所以转换前要用instanceof判断该父类是否是子类的实例才可。
这些都是我以前的一些笔记,希望能对你有点帮助。 参考技术B 当你使用A a = new C();的时候其实你声明的是一个A类只是你使用了C类去实体化他。那么A类在这里就有点像接口。你在C类中你重载了area()方法。所以你调用a.area()时就是C类中的内容。但是你的A类中的name属性你没有提供get和set方法并且int name = 3;这种方法将会使其默认为私有方式保存。虽然你在C类中使用了同样的声明int name = 4;但是虽然这两个属性其属性名相同但是他们指向不同的地址。事实上说是不同的变量。当你使用A.name调用属性时,由于声明时你声明的是A类那么它自然访问A类中的name属性。
当你使用C c = new C();的时候其实你声明的是一个C类你又使用了C类去实体化他。那么当你使用c.name时你访问的自然就是C类中的name属性了。
还有当你把A类中的area()方法删去但是A类中保留时。如果你使用如下的声明方式:
A a = new C();那么你声明了一个A类而且你使用C类去实体化他。因为A类中没有area()方法所以C类中的area()方法不会去实体化到这个声明中去(这有点像接口,你实例化接口也是一样的)。所以你调用a.area()自然会报错。因为A类没有这个方法。哪怕C类有这个方法你用C类去实体化也不会实体化这个方法的。 参考技术C 父类实体永远不可能转换成子类引用成功。
父类引用的实体本身是子类实例时能转换为子类引用。
子类实体可以用父类类型引用,也可以用子类本身类型引用。
父类实体只能用本身类型引用,除非该父类又是另一个类的子类。
子类拥有比父类多的功能,功能多的转换为功能少的可以,但是功能少的要转换为功能多的那是不可能的,因为它根本不具备某些方法。
子类和父类转换这句话应该说成是 子类实体(父类实体)转换为父类引用(子类引用)。 参考技术D 其实这是JAVA特性之一:多态。A a = new C()中编译的时候是编译A类,运行时运行C类,由于你用a.area()调用了area()方法,而子类C覆盖了该方法,因此会输出c类方法。还有,JAVA多态只适用于方法,与成员变量无关,推荐你看李刚的《疯狂的JAVA讲义》
java异常类子类和父类的关系
在java 中,当我们子类要重写父类中的方法,如果父类的方法有异常声明,那么子类重写这个方法时候,所要声明的异常不应该比父类的大。只能是小等,或者可以没有。原因如下。
假如我们自定意义一个异常:
public class MyException extends Exception {
public MyException(String message) {}
public MyException() {}
}
那么我们有一个父类它将有一个方法,将声明抛出这个异常。我们把它做成抽象的(无所谓)
public abstract class ParentException {
public abstract void test() throws MyException;
}
那么将有一个类使用到上面这个类
public class ExceptionTest {
private ParentException exception;
public ExceptionTest(ParentException exception){
this.exception=exception;
}
public void app(){
try {
exception.test();
} catch (MyException e) {
e.printStackTrace();
}
}
}
对于以上的try~catch 我们就直接捕获MyException异常。这是正确的,它在编译的时候是没有问题的。
假如,有一个ParentException的有一个子类
public class ChildException extends ParentException{
public void test() throws Exception{ }
}
他的方法可以声明抛出比父类大的异常,假如它是正确的。
那么问题来了。当我们执行ExceptionTest类的时候,我们以这个子类做为对象传进去。
exception.test();这个地方将在运行的时候实际调用的是ChildException这个子类的test()方法,而它的声明抛 出却是比父类大的异常,这就使得在ExceptionTest类中,捕获异常处出现了毛病,因为它无法捕获Exception异常。
综上所诉,子类重写父类的方法时候不能声明抛出比父类大的异常
顶
0
踩
以上是关于子类和父类的转换!谢谢!的主要内容,如果未能解决你的问题,请参考以下文章