电子商务网站建设与维护方法分析不包括最专业的做网站公司

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

电子商务网站建设与维护方法分析不包括,最专业的做网站公司,wordpress网站logo,专业邯郸网站建设文章目录对象的多态性多态的理解举例7.2 多态的好处和弊端7.3 虚方法调用(Virtual Method Invocation)7.4 成员变量没有多态性7.5 向上转型与向下转型7.6 为什么要类型转换呢#xff1f;7.7 如何向上转型与向下转型7.8 instanceof关键字7.9 复习#xff1a;类型转换7.10 练习… 文章目录对象的多态性多态的理解举例7.2 多态的好处和弊端7.3 虚方法调用(Virtual Method Invocation)7.4 成员变量没有多态性7.5 向上转型与向下转型7.6 为什么要类型转换呢7.7 如何向上转型与向下转型7.8 instanceof关键字7.9 复习类型转换7.10 练习对象的多态性 多态性是面向对象中最重要的概念在Java中的体现对象的多态性父类的引用指向子类的对象 格式父类类型指子类继承的父类类型或者实现的接口类型 父类类型 变量名 子类对象对象的多态在Java中子类的对象可以替代父类的对象使用。所以一个引用类型变量可能指向(引用)多种不同类型的对象 多态的理解 Java引用变量有两个类型编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定运行时类型由实际赋给该变量的对象决定。简称编译时看左边运行时看右边。 若编译时类型和运行时类型不一致就出现了对象的多态性(Polymorphism)多态情况下“看左边”看的是父类的引用父类中不具备子类特有的方法 “看右边”看的是子类的对象实际运行的是子类重写父类的方法 多态的使用前提① 类的继承关系 ② 方法的重写 举例 package com.atguigu.polymorphism.grammar;public class Pet {private String nickname; //昵称public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname nickname;}public void eat(){System.out.println(nickname 吃东西);} }package com.atguigu.polymorphism.grammar;public class Cat extends Pet {//子类重写父类的方法Overridepublic void eat() {System.out.println(猫咪 getNickname() 吃鱼仔);}//子类扩展的方法public void catchMouse() {System.out.println(抓老鼠);} }package com.atguigu.polymorphism.grammar;public class Dog extends Pet {//子类重写父类的方法Overridepublic void eat() {System.out.println(狗子 getNickname() 啃骨头);}//子类扩展的方法public void watchHouse() {System.out.println(看家);} }1、方法内局部变量的赋值体现多态 package com.atguigu.polymorphism.grammar;public class TestPet {public static void main(String[] args) {//多态引用Pet pet new Dog();pet.setNickname(小白);//多态的表现形式/编译时看父类只能调用父类声明的方法不能调用子类扩展的方法运行时看“子类”如果子类重写了方法一定是执行子类重写的方法体/pet.eat();//运行时执行子类Dog重写的方法 // pet.watchHouse();//不能调用Dog子类扩展的方法pet new Cat();pet.setNickname(雪球);pet.eat();//运行时执行子类Cat重写的方法} }2、方法的形参声明体现多态 package com.atguigu.polymorphism.grammar;public class Person{private Pet pet;public void adopt(Pet pet) {//形参是父类类型实参是子类对象this.pet pet;}public void feed(){pet.eat();//pet实际引用的对象类型不同执行的eat方法也不同} }package com.atguigu.polymorphism.grammar;public class TestPerson {public static void main(String[] args) {Person person new Person();Dog dog new Dog();dog.setNickname(小白);person.adopt(dog);//实参是dog子类对象形参是父类Pet类型person.feed();Cat cat new Cat();cat.setNickname(雪球);person.adopt(cat);//实参是cat子类对象形参是父类Pet类型person.feed();} }3、方法返回值类型体现多态 package com.atguigu.polymorphism.grammar;public class PetShop {//返回值类型是父类类型实际返回的是子类对象public Pet sale(String type){switch (type){case Dog:return new Dog();case Cat:return new Cat();}return null;} }package com.atguigu.polymorphism.grammar;public class TestPetShop {public static void main(String[] args) {PetShop shop new PetShop();Pet dog shop.sale(Dog);dog.setNickname(小白);dog.eat();Pet cat shop.sale(Cat);cat.setNickname(雪球);cat.eat();} }7.2 多态的好处和弊端 好处变量引用的子类对象不同执行的方法就不同实现动态绑定。代码编写更灵活、功能更强大可维护性和扩展性更好了。 弊端一个引用类型变量如果声明为父类的类型但实际引用的是子类对象那么该变量就不能再访问子类中添加的属性和方法。 Student m new Student(); m.school pku; //合法,Student类有school成员变量 Person e new Student(); e.school pku; //非法,Person类没有school成员变量// 属性是在编译时确定的编译时e为Person类型没有school成员变量因而编译错误。康师傅有话说 使用父类做方法的形参是多态使用最多的场合。即使增加了新的子类方法也无需改变符合开闭原则。 父类引用做方法的形参实参可以是任意的子类对象可以通过不同的子类对象实现不同的行为方式。另外即使增加了新的子类方法也无需改变提高了扩展性符合开闭原则。 补充开闭原则OCP 对扩展开放对修改关闭通俗解释软件系统中的各种组件如模块Modules、类Classes以及功能Functions等应该在不修改现有代码的基础上引入新功能 7.3 虚方法调用(Virtual Method Invocation) 在Java中虚方法是指在编译阶段不能确定方法的调用入口地址在运行阶段才能确定的方法即可能被重写的方法。 Person e new Student(); e.getInfo(); //调用Student类的getInfo()方法子类中定义了与父类同名同参数的方法在多态情况下将此时父类的方法称为虚方法父类根据赋给它的不同子类对象动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。 举例 前提Person类中定义了welcome()方法各个子类重写了welcome()。 执行多态的情况下调用对象的welcome()方法实际执行的是子类重写的方法。 拓展 静态链接或早起绑定当一个字节码文件被装载进JVM内部时如果被调用的目标方法在编译期可知且运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接。那么调用这样的方法就称为非虚方法调用。比如调用静态方法、私有方法、final方法、父类构造器、本类重载构造器等。 动态链接或晚期绑定如果被调用的方法在编译期无法被确定下来也就是说只能够在程序运行期将调用方法的符号引用转换为直接引用由于这种引用转换过程具备动态性因此也就被称之为动态链接。调用这样的方法就称为虚方法调用。比如调用重写的方法针对父类、实现的方法针对接口。 7.4 成员变量没有多态性 若子类重写了父类方法就意味着子类里定义的方法彻底覆盖了父类里的同名方法系统将不可能把父类里的方法转移到子类中。 对于实例变量则不存在这样的现象即使子类里定义了与父类完全相同的实例变量这个实例变量依然不可能覆盖父类中定义的实例变量
package com.atguigu.polymorphism.grammar;public class TestVariable {public static void main(String[] args) {Base b new Sub();System.out.println(b.a);System.out.println(((Sub)b).a);Sub s new Sub();System.out.println(s.a);System.out.println(((Base)s).a);} } class Base{int a 1; } class Sub extends Base{int a 2; }7.5 向上转型与向下转型 首先一个对象在new的时候创建是哪个类型的对象它从头至尾都不会变。即这个对象的运行时类型本质的类型用于不会变。但是把这个对象赋值给不同类型的变量时这些变量的编译时类型却不同。 7.6 为什么要类型转换呢 因为多态就一定会有把子类对象赋值给父类变量的时候这个时候在编译期间就会出现类型转换的现象。 但是使用父类变量接收了子类对象之后我们就不能调用子类拥有而父类没有的方法了。这也是多态给我们带来的一点小麻烦。所以想要调用子类特有的方法必须做类型转换使得编译通过。 向上转型当左边的变量的类型父类 右边对象/变量的类型子类我们就称为向上转型 此时编译时按照左边变量的类型处理就只能调用父类中有的变量和方法不能调用子类特有的变量和方法了但是运行时仍然是对象本身的类型所以执行的方法是子类重写的方法体。此时一定是安全的而且也是自动完成的 向下转型当左边的变量的类型子类右边对象/变量的编译时类型父类我们就称为向下转型 此时编译时按照左边变量的类型处理就可以调用子类特有的变量和方法了但是运行时仍然是对象本身的类型不是所有通过编译的向下转型都是正确的可能会发生ClassCastException为了安全可以通过isInstanceof关键字进行判断
7.7 如何向上转型与向下转型 向上转型自动完成 向下转型子类类型父类变量 package com.atguigu.polymorphism.grammar;public class ClassCastTest {public static void main(String[] args) {//没有类型转换Dog dog new Dog();//dog的编译时类型和运行时类型都是Dog//向上转型Pet pet new Dog();//pet的编译时类型是Pet运行时类型是Dogpet.setNickname(小白);pet.eat();//可以调用父类Pet有声明的方法eat但执行的是子类重写的eat方法体 // pet.watchHouse();//不能调用父类没有的方法watchHouseDog d (Dog) pet;System.out.println(d.nickname d.getNickname());d.eat();//可以调用eat方法d.watchHouse();//可以调用子类扩展的方法watchHouseCat c (Cat) pet;//编译通过因为从语法检查来说pet的编译时类型是PetCat是Pet的子类所以向下转型语法正确//这句代码运行报错ClassCastException因为pet变量的运行时类型是DogDog和Cat之间是没有继承关系的} }7.8 instanceof关键字 为了避免ClassCastException的发生Java提供了 instanceof 关键字给引用变量做类型的校验。如下代码格式 //检验对象a是否是数据类型A的对象返回值为boolean型 对象a instanceof 数据类型A 说明 只要用instanceof判断返回true的那么强转为该类型就一定是安全的不会报ClassCastException异常。如果对象a属于类A的子类Ba instanceof A值也为true。要求对象a所属的类与类A必须是子类和父类的关系否则编译错误。
示例代码 package com.atguigu.polymorphism.grammar;public class TestInstanceof {public static void main(String[] args) {Pet[] pets new Pet[2];pets[0] new Dog();//多态引用pets[0].setNickname(小白);pets[1] new Cat();//多态引用pets[1].setNickname(雪球);for (int i 0; i pets.length; i) {pets[i].eat();if(pets[i] instanceof Dog){Dog dog (Dog) pets[i];dog.watchHouse();}else if(pets[i] instanceof Cat){Cat cat (Cat) pets[i];cat.catchMouse();}}} }7.9 复习类型转换 基本数据类型的Casting 自动类型转换小的数据类型可以自动转换成大的数据类型 如long g20; double d12.0f强制类型转换可以把大的数据类型强制转换(casting)成小的数据类型 如 float f(float)12.0; int a(int)1200L 对Java对象的强制类型转换称为造型 从子类到父类的类型转换可以自动进行从父类到子类的类型转换必须通过造型(强制类型转换)实现无继承关系的引用类型间的转换是非法的在造型前可以使用instanceof操作符测试一个对象的类型 举例 public class ConversionTest {public static void main(String[] args) {double d 13.4;long l (long) d;System.out.println(l);int in 5;// boolean b (boolean)in;Object obj Hello;String objStr (String) obj;System.out.println(objStr);Object objPri new Integer(5); //Object是Integer的父类符合向上转型编译不报错// 所以下面代码运行时引发ClassCastException异常String str (String) objPri; //Integer和String无继承关系运行时报错} }7.10 练习 练习1笔试面试 题目1继承成员变量和继承方法的区别 class Base {int count 10;public void display() {System.out.println(this.count);} }class Sub extends Base {int count 20;public void display() {System.out.println(this.count);} }public class FieldMethodTest {public static void main(String[] args){Sub s new Sub();System.out.println(s.count);s.display();Base b s;System.out.println(b s);System.out.println(b.count); //10 成员变量无多态性b.display(); //20 调用子类重写的父类的方法} } 题目2 //考查多态的笔试题目 public class InterviewTest1 {public static void main(String[] args) {Base base new Sub();base.add(1, 2, 3); //sub_1// Sub s (Sub)base; // s.add(1,2,3); //sub_2} }class Base {public void add(int a, int… arr) {System.out.println(base);} }class Sub extends Base {public void add(int a, int[] arr) { //int… arr int[] arr看作父类方法的重写System.out.println(sub_1);}// public void add(int a, int b, int c) { // System.out.println(sub_2); // }}