java 继承小结
[code=java]
//多态的经典例子
//向上转型后,父类只能调用子类和父类的共同方法和的重写方法(方法名相同,参数也相同),不能调用重载方法(方法名相同,但参数不同)
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A{
public String show(B obj){//重载
return ("B and B");
}
public String show(A obj){//重写
return ("B and A");
}
}
class C extends B{ }
class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();//向上转型
B b = new B();
C c = new C();
D d = new D(); System.out.println("1--" + a1.show(b));//A and A this.show((super)O)
System.out.println("2--" + a1.show(c));//A and A this.show((super)(super)O)
System.out.println("3--" + a1.show(d));//A and D this.show(O)
System.out.println("4--" + a2.show(a1));//B and A super.show(O)
System.out.println("4--" + a2.show(b));//B and A super.show((super)O)
System.out.println("5--" + a2.show(c));//B and A super.show((super)O)
System.out.println("6--" + a2.show(d));//A and D super.show((super)O)
System.out.println("7--" + b.show(b));//B and B
System.out.println("8--" + b.show(c));//B and B
System.out.println("9--" + b.show(d));//A and D }
}
/*
多态机制遵循的原则概括为:
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,
也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,
该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
*/ [/code]
abstract class Animal
{
public abstract void eat();
}
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
} class Dog extends Animal
{
public void eat()
{
System.out.println("吃骨头");
}
public void kanJia()
{
System.out.println("看家");
}
} class Pig extends Animal
{
public void eat()
{
System.out.println("饲料");
}
public void gongDi()
{
System.out.println("拱地");
}
}
class Function
{
public static void function(Animal a){
a.eat();
if(a instanceof Cat){
Cat c=(Cat)a;
c.catchMouse();
}
if(a instanceof Dog){
Dog d=(Dog)a;
d.kanJia();
}
//instanceof :用于判断对象的具体类型,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。
if(a instanceof Pig){
Pig p=(Pig)a;
p.gongDi();
}
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Function.function(new Cat());
Function.function(new Dog());
Function.function(new Pig()); //Animal a = new Cat();//类型提升。 向上转型。
//a.eat(); //如果想要调用猫的特有方法时,如何操作?
//强制将父类的引用。转成子类类型。向下转型。
//Cat c = (Cat)a;
//c.catchMouse(); Animal a = new Cat();//向上转型
a.eat();
//a.catchMouse(); 向上转型后不能再用子类的特有方法,想要使用必须再向下转型
Cat c = (Cat)a;//子类向上转化为父类后才能向下转型
c.catchMouse(); //Dog d=(Dog)a;
//d.kanJia(); 这样做是错误的,没有实现 //下面这样也是错误的
/*
Animal e=new Animal() { @Override
public void eat() {
System.out.println("eee"); }
};
e.eat(); Dog f=(Dog)e;
f.eat();
f.kanJia();
*/ //千万不要出现这样的操作:就是将父类对象转成子类类型。
//我们能转换的是父类引用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。
//多态自始至终都是子类对象在做着变化。
}
}
class ExtendsDemo{
     public static void main(String[] args){
          Zi z = new Zi();//>构造函数最先执行,见下面的说明
          z.show();
     }
}
class Fu{
    Fu(){
           show();
    }
    void show(){//被子类覆盖了,所以运行的是子类的show方法
          System.out.println("fu show" );
    }
}
class Zi extends Fu{
     int num = 8;//>构造函数最先执行
     Zi(){
           //隐式的super();
           //通过super初始化父类内容时,子类的成员变量并未显示初始化,
           //等super()父类初始化完毕后,才进行子类的成员变量显示初始化
     }
     void show(){
          System.out.println("zi show..." + num);
     }
}
/*
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的所有构造函数默认第一行有一条隐式的语句 super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super()。
以Person p = new Person();为例:
   1. JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况下)。
   2. 在内存中开辟空间,并分配地址。
   3. 并在对象空间中,对对象的属性进行默认初始化。
   4. 调用对应的构造函数进行初始化。
   5. 在构造函数中,第一行会先到调用父类中构造函数进行初始化。
   6. 父类初始化完毕后,再对子类的属性进行显示初始化。
   7. 再进行子类构造函数的特定初始化。
   8. 初始化完毕后,将地址值赋值给引用变量。
 覆盖:
1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2.静态只能覆盖静态。
3.父类中的私有方法不可以被覆盖。父类为static的方法无法覆盖。
4.重载:只看同名函数的参数列表。重写:子父类方法要一模一样。
*/
/*
class Fu{
    int num ;
    Fu(){
          num = 10;
          System.out.println("A fu run" );
    }
    Fu(int x){
          System.out.println("B fu run..." + x);
    }
}
class Zi extends Fu{
    Zi(){
          //super();//默认调用的就是父类中的空参数的构造函数
          System.out.println("C zi run " + num);
    }
    Zi(int x){
          super(4);
          System.out.println("D zi run " + x);
    }
}
class ExtendDemo{
     public static void main(String[] args){
          new Zi();
          System.out.println("-------------------" );
          new Zi(6);
    }
}
*/
public class Animal {
    public static void main(String[] args) {
        //将一个衍生类引用转换为其基类引用,这叫做向上转换
        /*
         * 向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口
        person b;
        b= new lgj();//定义了b为父类,又将子类的引用赋给b,下面为简写
        */
        person b=new lgj(); //子类对象当成父类对象,只能调用父类定义过的的成员和方法,
        //如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。
        b.eat();
        //b.fly();  //此处提示在Animal中没有定义fly方法。
//向下转型:父类引用的对象转换为子类类型称为向下转型。
//我们可以将一个基类引用向下转型(downcast)成为衍生类的引用,但要求该基类引用所指向的对象,
//已经是所要downcast的衍生类对象。比如可以将上面的lgj向上转型为person类引用后,再向下转型成为lgj类引用。
        lgj c =(lgj)b;//b已经是父类的引用,强制转型为子类的引用c
        c.eat();
        c.fly();
//或者:
//向下转型时,如果父类的引用一开始就指向子类对象,那么转型之后是安全的,若果父类的引用一开始指向的不是子类对象,
//那么转型成子类对象时,编译不会出错,运行时会显示ClassCastException。我们可以通过关键字instanceof来检测安全性
        lgj f=new lgj();
        person d=f; //向上转型
       // person d=new person();
        System.out.println("aaaa");
        if(d instanceof lgj){
            lgj e=(lgj)d;//向下转型,这条语句不会执行,因为d对象指向的不是类lgj实例化的对象
            e.eat();
            e.fly();
        }
    }
}
class person {
    public void eat(){
        System.out.println("person eatting...");
}
}
class lgj extends person{
    public void eat(){
              System.out.println("lgj eatting...");
    }
    public void fly(){
            System.out.println("lgj flying...");
    }
}
/*
 * 总结:
1、父类引用可以指向子类对象,子类引用不能指向父类对象。
2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。
   如Father father = new Son();
3、把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。
   如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;
   其中father前面的(Son)必须添加,进行强制转换。
4、upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效
5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。
#对比基础类型转换
如果我们从一个高精度类型转换到低精度类型,比如从float转换到int,那么我们有可能会损失信息。
这样的转换叫做收缩变换(narrowing conversion)。这种情况下,我们需要显示的声明类型转换
int a;
a = (int) 1.23;
如果我们从低精度类型转换成高精度类型,则不存在信息损失的顾虑。这样的变换叫做宽松变换(widening conversion)。
我们不需要显示的要求类型转换,Java可以自动进行:
int a = 3;
double b;
b = a;
父类 >>高精度
子类 >>低精度
*/ 
java 继承小结的更多相关文章
- Java序列化小结
		title: Java序列化小结 date: 2017-05-06 20:07:59 tags: 序列化 categories: Java基础 --- Java序列化就是将一个对象转化成一串二进制表示 ... 
- Java  基础--小结
		Java 基础--小结 java基础 Java源程序(.java文件)——>java字节码文件(.class文件)——>由解释执行器(java.exe)将字节码文件加载到java虚拟机( ... 
- Java继承与组合
		Java继承与组合 继承 java 中使用extends关键字表示继承关系,当创建一个类时,如果没有明确指出要继承的类,则是隐式地从根类Object进行继承. 子类继承父类的成员变量 子类能够继承父类 ... 
- JAVA继承时构造函数的问题
		今天看到java继承部分时,关于构造函数是否继承以及如何使用时遇到了点问题,后来查找相关资料解决了. 下面是我个人的总结: 先创建一个父类,里面有两个构造函数: public class Jisuan ... 
- Java中文编码小结
		Java中文编码小结 1. 只有 字符到字节 或者 字节到字符 的转换才存在编码转码; 2. Java String 采用 UTF-16 编码方式存储所有字符.unicode体系采用唯一的码点表示唯一 ... 
- Java继承和接口
		接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础类.使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以及规定它仅仅是一个接口.这样便带来了一 ... 
- Java继承的初始化
		/** * Created by xfyou on 2016/11/2. * Java继承的初始化 */ public class Beetle extends Insect { int k = pr ... 
- Java—继承、封装、抽象、多态
		类.对象和包 1) 面向对象编程(Object Oriented Programming ,简称 OOP):20世纪70年代以后开始流行. 2) 结构化编程与面向对象编程的区别: A. 在结构化编程中 ... 
- java继承关系中成员变量,构造方法,成员方法的关系
		Java继承中的成员关系 A:成员变量 a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单写那个名字就访问那个名字! b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ... 
随机推荐
- 字符串查找算法的改进-hash查找算法
			字符串查找即为特征查找: 特征即位hash: 1.将待查找的字符串hash: 2.在容器字符串中找头字符匹配的字符串,并进行hash: 3.比较hash的结果:相同即位匹配: hash算法的设计为其中 ... 
- JSONObject数组排序工具类
			依赖jar <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</a ... 
- CDH4.5.0下安装snappy
			编译源代码 http://www.cnblogs.com/chengxin1982/p/3862289.html 测试参考 http://blog.jeoygin.org/2012/03/java-c ... 
- HTML第三章:表单
			第三章:表单 表单标签form:<form></form>//相当于一张记录用户信息的单子 常用属性:method:表单的提交方式,常用的值有两个 ... 
- Python 初始—(函数·)
			过程是没有返回值的函数,有一系列的函数组合和逻辑功能结合即为过程: def 定义函数: def 函数名(): print("") 位置参数和关键字调用,根据位置参数优先,关键字参数 ... 
- using namespace std 是什么意思?
			摘录CSDN上面大牛的回答简要意思就是使用标准库,想知道更清楚的继续读下面的. using namespace std 意思: using 和namespace都是C++的关键词. ... 
- POJ2409 Let it Bead(Polya定理)
			Let it Bead Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6443 Accepted: 4315 Descr ... 
- 设置vim tab为4个空格
			Vim 编辑器默认tab为8个空格,但对于pythoner来说,必须要调整到4个空格. 方法如下: 在~/.vimrc文件中加入下面设置: set ts=4 #设置tabstop为4个空格 set e ... 
- 【CodeBase】PHP打印所有用户自定义常量
			print_r(get_defined_constants(true)['user']); 
- python -- configparse读取配置文件
			在开发过程中,有的时候需要将一些参数写入到配置文件中,这样在改动一些相关信息时,可以直接在配置文件中进行修改. 而在python中,可以通过内置模块configparse对标准的配置文件进行读取. 配 ... 
