当前位置: 首页 > news >正文

网站首页结构布局哈尔滨建设网站的免费咨询

网站首页结构布局,哈尔滨建设网站的免费咨询,网站短信验证怎么做,Wordpress管理媒体库目录 1. 向上转型和向下转型 1.1 向上转型 1.2 向下转型 1.3 instanceof关键字 2. 重写#xff08;overidde#xff09; 2.1 方法重写的规则 2.1.1 基础规则 2.1.2 深层规则 2.2 三种不能重写的方法 final修饰 private修饰 static修饰 3. 动态绑定 3.1 动态绑…目录 1. 向上转型和向下转型 1.1 向上转型 1.2 向下转型 1.3 instanceof关键字 2. 重写overidde 2.1 方法重写的规则 2.1.1 基础规则 2.1.2 深层规则 2.2 三种不能重写的方法 final修饰 private修饰  static修饰 3. 动态绑定 3.1 动态绑定的概念 3.2 动态绑定与静态绑定 4. 多态 4.1 多态的实现场景 1. 基类形参方法  2. 基数组 4.2 多态缺陷 1. 属性(字段)没有多态性  2. 向上转型不能使用子类特有的方法 3. 构造方法没有多态性 上一篇文章中我们深度学习了继承的概念与实现。在继承篇中我们最重要的就是“弄清楚通过子类实例变量来访问与父类相同的成员会怎么样”而在多态篇中最核心的内容就是“弄清楚通过父类实例变量来访问与子类相同的方法会怎么样”。 1. 向上转型和向下转型 在了解多态之前我们还要补充几个知识点这首先就是向上转型和向下转型。 1.1 向上转型 向上转型是指将一个子类对象的引用赋值给一个父类类型的实例变量。 语法格式 父类类型 对象名 new 子类类型() //例如 Animal animal new Cat(小咪, 2); animal是父类类型的实例变量但引用的是一个子类Cat对象因为这是从小范围向大范围的转换。类似基础数据类型中的隐式类型转换例如长整形long接收整形int的数据 向上转型的3种使用场景 直接赋值子类对象的引用直接赋值给父类类型的实例变量。方法传参子类对象的引用作为参数传递给方法中的父类类型的形参。方法返回方法的返回类型是父类类型返回的值是子类类型。 例如 public class TestAnimal {// 2. 方法传参形参为父类型引用可以接收任意子类的对象public static void eatFood(Animal a){a.eat();}// 3. 作返回值返回任意子类对象public static Animal buyAnimal(String var){if(狗.equals(var) ){return new Dog(狗狗,1);}else if(猫 .equals(var)){return new Cat(猫猫, 1);}else{return null;}}public static void main(String[] args) {Animal cat new Cat(元宝,2); // 1. 直接赋值子类对象赋值给父类对象Dog dog new Dog(小七, 1);eatFood(cat);eatFood(dog);Animal animal buyAnimal(狗);animal.eat();animal buyAnimal(猫);animal.eat();}} 1.2 向下转型 向下转型是将父类对象强制转换为子类对象的过程需要用到类型转换运算符( ) 。 【注意】 只能对已向上转型的对象进行向下转型不能直接将一个父类对象强制转换为子类对象除非这个父类对象实际上是子类对象的向上转型。也就是说必须先创建一个子类对象然后将其向上转型为父类对象最后再进行向下转换。向上转型的子类类型 与 向下接收的子类类型必须一致。 例如 先看父类和子类的具体代码 public class Animal {public String name;public Animal(String name){this.name name;}public void eat(){System.out.println(name在吃东西);} }public class Dog extends Animal{public Dog(String name){super(name);}public void eat(){System.out.println(name在吃狗粮);}//Dog类的专属方法public void bark(){System.out.println(name在汪汪叫);} }public class Cat extends Animal{public Cat(String name){super(name);}public void eat(){System.out.println(name在吃猫粮);}//Cat类的专属方法public void mew(){System.out.println(name在喵喵叫);} } 测试1父类实例animal是Dag类的向上转型再让animal向下转型传给子类实例dog。 public class Test {public static void main(String[] args) {Animal animal new Dog(旺财);Dog dog;dog (Dog) animal;dog.bark();} } 运行成功 测试2父类实例animal是Dag类的向上转型再让animal向下转型传给子类实例cat。向上转型的子类与向下接收的子类不一致 public class Test {public static void main(String[] args) {Animal animal new Dog(旺财);Cat cat;cat (Cat) animal;//抛出异常} } 抛出异常 1.3 instanceof关键字 向下转型用的比较少而且不安全万一转换失败运行时就会抛异常。Java中为了提高向下转型的安全性引入了instanceof关键字。 语法         Object  instanceof  ClassName 其中object 是要测试的对象或实例变量ClassName 是要测试的类名。 作用和返回值 如果 object 是 ClassName 的实例或其子类的实例则表达式返回 true否则返回 false。 有了instanceof我们向下转型就可以更安全了 public class TestAnimal {public static void main(String[] args) {Cat cat new Cat(元宝,2);Dog dog new Dog(小七, 1);// 向上转型Animal animal cat;animal.eat();animal dog;animal.eat();if(animal instanceof Cat){ //检查类型cat (Cat)animal;cat.mew();}if(animal instanceof Dog){ //检查类型dog (Dog)animal;dog.bark();}}} animal最后是Dog类的引用所以通过了第2个检查由dog接收animal的向下转型。 2. 重写overidde 2.1 方法重写的规则 2.1.1 基础规则 方法重写也称为方法覆盖即外壳不变核心重写。 子类在重写父类的方法时一般必须与父类的方法原型一致【返回值类型、方法名、参数列表要完全一致】。 重写的方法可以在子类方法头的上一行使用“ Override ”注解来显式指定。有了这个注解能帮我们进行一些合法性校验。例如不小心将方法名字拼写错了比如eat写成 aet那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写 例如 如果显示指定overidde但方法与父类原型不一致的话系统会报错 2.1.2 深层规则 返回值类型其实子类重写的方法返回类型也可以与父类不一样但是必须是具有父子关系的。         该要求其实隐藏了一个情况那就是此时的方法返回值类型是类类型的。 对于这种情况的方法重写父类方法的返回值类型 必须是 子类方法的返回值类型的 基类。 访问限定符访问权限不能比父类中被重写的方法的访问权限更低。(即子类重写的方法访问权限可以更宽松不能更严格) 对于“返回值类型”要求的举例 ​class Parent {public Number display() {return 42; // 返回一个Integer类型的值} }class Child extends Parent {// 重写父类的display方法并改变返回类型为Double这是允许的因为Double是Number的子类型Overridepublic Double display() {return 42.0;} }public class Test {public static void main(String[] args) {Parent parent new Parent();System.out.println(parent.display()); // 输出: 42Child child new Child();System.out.println(child.display()); // 输出: 42.0} } Parent类的display方法的返回类型是Number类Child类的display方法的返回类型是Double类。其中Parent类是Child类的父类Number类又是Double类和Interger类的父类这符合方法重写的深层规则。 如果该例子中的 方法返回值类型的父子关系反过来 会报错 对于“访问限定符”要求的举例 关于方法重写还有更深层更严格的规定这些规定与异常、线程等有关。本章重点是继承与多态所以不再具体展开。 2.2 三种不能重写的方法 如果父类方法被final、private或static修饰则子类不能重写该方法。 final修饰 final final修饰成员方法时就是用来防止该方法被子类重写 或者 不想让该方法被重写。 例如 private修饰  private 当父类的方法被private修饰时说明这个方法是父类私有的子类也没有办法去访问该方法。 如果private修饰了父类的方法子类又写了一个与父类方法原型一样的方法系统并不会报错。 (因为系统检查方法重写时会自动把父类的私有方法忽略掉)如果private修饰了子类的方法父类又有一个与子类方法原型一样的非private方法那么系统会报错。 (此时系统会认为你想要让子类重写父类方法又因为重写后的方法是私有的而父类的方法非私有所以会提醒你“分配了更低的访问权限”并报错) 例1 父类方法是私有的build没有问题 例2 子类方法是私有的父类方法原型与子类一致。系统认为你要重写但子类的方法权限更低所以报错 static修饰 static 静态方法是在类加载时就绑定到类本身而不是在运行时绑定到具体的对象实例所以static修饰的方法不能被重写。即静态方法不能实现动态绑定也就不能被覆盖(重写)。 例如 虽然静态方法是可以被继承的但如果子类定义了一个与父类相同签名的静态方法这只是对父类静态方法的一种隐藏而非真正意义上的重写。 子类对象向上转型后当通过父类实例变量引用调用该方法时仍然会执行父类的静态方法而不是子类的静态方法。 例如 class Parent {static void display() {System.out.println(Parent display method);} }class Child extends Parent {static void display() {System.out.println(Child display method);} }public class Test {public static void main(String[] args) {Parent parent1 new Parent();parent1.display(); //调用父类静态方法Child child new Child();child.display(); //调用子类静态方法Parent parent2 new Child(); //向上转型parent2.display(); //调用父类静态方法} } 3. 动态绑定 3.1 动态绑定的概念 刚刚在解释static修饰方法时我们提到了一个词叫动态绑定。下面让我们看看什么是动态绑定。 概念 动态绑定也叫后期绑定是指在运行时根据对象的实际类型来确定调用哪个方法而不是在编译时就决定。当一个父类引用指向其子类的对象并且通过该引用调用一个被重写的方法时会在运行时根据对象的实际类型来调用相应的方法实现这就是重写方法的动态绑定。 动态绑定重写方法的实现条件 存在继承关系必须有一个基类父类和至少一个派生类子类子类继承自父类。方法重写子类要实现父类中至少一个方法的重写。向上转型在程序中存在向上转型的情况即把子类对象的引用赋值给父类的实例变量。 例如 class Animal {public String name;public Animal(String name){this.name name;}public void eat(){System.out.println(name在吃东西);} }public class Dog extends Animal{public Dog(String name){super(name);}public void eat(){System.out.println(name在吃狗粮);} }public class Cat extends Animal{public Cat(String name){super(name);}public void eat(){System.out.println(name在吃猫粮);} }public class Test {public static void main(String[] args) {Animal animal new Animal(动物);//animal动态绑定到Animal类animal.eat();animal new Dog(小狗);//animal动态绑定到Dog类animal.eat();animal new Cat(小猫);//animal动态绑定到Cat类animal.eat();} } 3.2 动态绑定与静态绑定 静态绑定也称为早期绑定是指在程序编译时就已经确定了方法调用的具体对象和方法实现。与动态绑定相对应静态绑定不需要在运行时进行额外的判断和查找来确定调用哪个方法。 静态绑定的适用情况 基本数据类型的方法调用(可重载的方法)对于基本数据类型的操作方法如数学运算等通常是静态绑定。例如int a 5; int b 10; int c a b; 中  运算符对应的加法方法是在编译时就确定的。私有方法、静态方法和 final 方法这些方法不能被重写或具有特殊的性质所以它们的调用可以在编译时确定。例如class Example { private void privateMethod() {...} static void staticMethod() {...} final void finalMethod() {...} } 中的私有方法、静态方法和 final 方法都是静态绑定的。构造方法构造方法在创建对象时被调用每个类都有特定的构造方法且在编译时就可以确定是哪个类的构造方法会被调用。例如new Example() 会调用 Example 类的构造方法这是在编译时就已经决定的。 方法重载静态绑定是一个类的多态性表现【例如工具类Arrays】而方法重写动态绑定是子类与父类间的多态性的表现。 4. 多态 多态的概念 去完成某个行为时当不同的对象去完成时会产生出不同的状态。又或者同一件事情发生在不同对象身上就会产生不同的结果。 打个比方语文老师要求同学们背一首诗同学A背了一首李白的诗、同学B背了一首杜甫的诗、同学C背了一首李清照的诗……每个同学背的诗都不同但不管怎么说他们都完成了“背一首诗”的任务这就是多态。 4.1 多态的实现场景 在java中要实现多态必须要满足如下几个条件缺一不可 必须在继承体系下 子类必须要对父类中方法进行重写 通过父类的引用调用 下面我来介绍两种常见的多态实现。 1. 基类形参方法  基类形参方法指的是形参数据类型为基类类型的方法。 该方法的形参的类型是父类类型我们一般在该方法中使用被重写的方法。不同的子类实例变量传参进去并发生向上转型该基类形参方法就能够通过动态绑定来调用不同的重写方法从而实现多态。 例如 //有继承关系的类 public class Animal {public String name;public Animal(String name){this.name name;}public void eat(){System.out.println(name在吃东西);} }public class Dog extends Animal{public Dog(String name){super(name);}public void eat(){System.out.println(name在吃狗粮);} }public class Cat extends Animal{public Cat(String name){super(name);}public void eat(){System.out.println(name在吃猫粮);} } ———————————————————————————————————————————————————————— ———————————————————————————————————————————————————————— //含基类形参方法的类 public class Test {public void eat(Animal animal){ //基类形参方法animal.eat();}public static void main(String[] args) {Test test new Test(); //如果Test的eat方法是静态方法那么可以不用new一个Test对象test.eat(new Animal(小动物));test.eat(new Dog(小狗));test.eat(new Cat(小猫));} } 这种方法有点类似C语言中的函数指针和回调函数的用法。详细请看《指针之旅4—— 指针与函数函数指针、转移表、回调函数》 2. 基数组 基数组指的是数组元素的类型都是基类类型。 由于可以向上转型在基数组中可以存放子类对象从而实现多态。 有点类似C语言中的函数指针数组 例如 ​//Animal类、Dog类和Cat类的内容如上面的一致 public class Test {public static void main(String[] args) {//基数组animalsAnimal[] animals {new Animal(小动物), new Dog(小狗), new Cat(小猫)};for(Animal x: animals){x.eat(); //临时变量x通过动态绑定实现多态}} } 如果有新的动物增加我们可以在基数组animals中添加这就是多态的好处十分便捷。 如果不基于多态来实现刚刚的代码内容我们需要多个if-else语句如下 在这种情况下如果要增加一个动物不仅字符串数组animals要变而且在for-each循环中还要加多一条else-if语句十分不便。 4.2 多态缺陷 1. 属性(字段)没有多态性  当父类和子类都有同名属性的时候通过父类实例变量引用只能引用父类自己的成员属性。 例如 public class Parent {public String str parent; }public class Child extends Parent{public String str child; }public class Test {public static void main(String[] args) {Parent parent new Parent();System.out.println(parent.str);//打印parentChild child new Child();System.out.println(child.str);//打印childparent child; //向上转型System.out.println(parent.str);//属性没有多态性打印的还是父类的str} } 2. 向上转型不能使用子类特有的方法 方法调用在编译时进行类型检查编译器只检查引用变量类型中定义的方法而不考虑实际对象的类型。 例如这里子类Dog比父类Animal类多了一个特殊方法bark()。如果用Animal类型的实例变量来接收Dog类的对象我们会发现无法通过该实例变量调用bark方法 3. 构造方法没有多态性 当父类的构造方法中调用一个被重写的方法时实际执行的是子类中的实现。然而此时子类可能还未完成初始化其成员变量尚未赋值或处于默认状态这就可能导致程序行为不确定甚至引发错误。 父类构造方法中如果调用了被重写的方法那么该重写的方法使用的是子类的方法。 我们创建两个类, B 是父类, D 是子类. D 中重写 func 方法. 并且在 B 的构造方法中调用 func ​ class B {public B() {// do nothingfunc();}public void func() {System.out.println(B.func());} }class D extends B {private int num 10;Overridepublic void func() {System.out.println(D.func() num);} }public class Test {public static void main(String[] args) {D d new D();} }​ 构造 D 对象的同时会调用 B 的构造方法.B 的构造方法中调用了 func 方法 此时会触发动态绑定会调用到 D 中的 func 。此时 D 对象自身还没有构造此时 num 处在未初始化的状态值为 0.如果具备多态性num的值应该是10. 结论: 用尽量简单的方式使对象进入可工作状态, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触 发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题。 本期分享完毕感谢大家的支持Thanks♪(ω)
http://www.dnsts.com.cn/news/19941.html

相关文章:

  • 一个企业做网站的目的网站推广运营公司
  • 达人设计网官方网站python做网站设计
  • 网站图片相册代码wordpress模板制作
  • 公司网站运营公司排名wordpress仿58同城
  • 绵阳网站建设信赖辉煌外贸公司网站怎么做
  • 计算机网站建设维护的基本知识摄影公司网站
  • 手机网站报价单模板下载最近的热点新闻
  • 游戏直播网站怎么做的wordpress 即将跳转
  • 手机网站模板源码区块链app开发价格
  • 网站的页面布局广州aso优化
  • 网站建设友链交换电脑十大免费游戏网站
  • 把自己做的网站进行app封包html改变字体大小代码
  • 网站建设制作视频广网站建设
  • 网站建设不一定当地培训网站有哪些
  • 北京公司建网站要多少费用兰州网站制作培训班
  • 网站建设是否属于技术合同旅行社酒店分销平台
  • 那种软件可以做视频网站wordpress移除密码保护
  • 建行网站首页登录常见的跨境电商平台有哪些?
  • 什么网站是最全的discuz网站模板下载器
  • 深圳网站建设骏域网站建设wordpress商店网页
  • 企业做自己的网站要注意什么wordpress 主题管理
  • 域名访问网站的知识手工灯笼简单又好看
  • 怎么做qq盗号网站wordpress中文对照
  • 上海网站建设宣传it 网站模板
  • 如何将vs做的网站备份出来6绍兴网站开发公司
  • 域名备案网站源码什么是网站开发公司电话
  • dreamware做网站首页衡水seo优化
  • 公司网站建设工作室门户网站 模板之家
  • 做网站基本费用大概需要多少跨境电商平台一览表
  • 免费做mc皮肤网站博物馆设计公司哪个好