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:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 子 ...
随机推荐
- Java从入门到放弃——02.常量、变量、数据类型、运算符
本文目标 理解什么是常量,什么是变量 认识八大基本数据类型 了解算数运算符.赋值运算符.关系运算符.逻辑运算符.位运算符.三元运算符 1.什么是常量与变量? 常量是相对静止的量,比如整数:1,2,3 ...
- 正则表达式 /i /g /m /ig /gi
正则表达式中/i,/g,/ig,/gi,/m的区别和含义 /i (忽略大小写) /g (全文查找出现的所有匹配字符) /m (多行查找) / /ig(全文查找.忽略大小写)
- border-radius给元素加圆角边框
border-radius给元素加圆角边框 例: border-radius:20px; /*所有角都使用半径为20px的圆角*/ 实心圆: 把宽度(width)与高度(height)值设置为一致(也 ...
- javaweb基础(39)_数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- 头部导航悬浮,css
.header{ position:fixed; z-index:100; left:; right:; } 如图.
- Rxjava+retrofit+mvp整合
转载请标明出处: http://blog.csdn.net/forezp/article/details/52621898 本文出自方志朋的博客 最近在看Rxjava,写了一个简单的 demo整合了R ...
- java基础 静态 static 问在多态中,子类静态方法覆盖父类静态方法时,父类引用调用的是哪个方法?
多态 package com.swift.jiekou; public class Jicheng_Tuotai_jingtai_diaoyong { public static void main( ...
- mybatis两级缓存原理剖析
https://blog.csdn.net/zhurhyme/article/details/81064108 对于mybatis的缓存认识一直有一个误区,所以今天写一篇文章帮自己订正一下.mybat ...
- 交换机基础配置之结合以太通道的vlan设置
我们将以上面的拓扑图来做实验,建立以太通道,并设置好vlan,将pc1和pc3放在同一vlan,将pc2和pc4放在同一vlan,同一vlan能跨交换机通信 在一切还没布置之前,四台pc机都在同一网段 ...
- Centos7上docker的安装和基本使用
Centos7上Docker的相关操作 Docker的安装 1.检查内核版本 docker使用linux的内核必须是3.10以上,首先需要 # uname -r 2.使用yum安装docker # y ...