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

自己怎样建设网站学编程从哪儿入手

自己怎样建设网站,学编程从哪儿入手,东营局域网设计,湛江建站免费模板目录 1. 多态的概念 2. 多态实现条件 3. 重写 重写与重载的区别 4. 向上转型和向下转型 4.1 向上转型 4.2 向下转型 5. 多态的优缺点 6. 避免在构造方法中调用重写的方法 我们从字面上看多态两个字, 多态就是有多种状态/形态. 比如一个人可以有多种状态, …目录 1. 多态的概念 2. 多态实现条件 3. 重写 重写与重载的区别 4. 向上转型和向下转型 4.1 向上转型 4.2 向下转型 5. 多态的优缺点 6. 避免在构造方法中调用重写的方法 我们从字面上看多态两个字, 多态就是有多种状态/形态. 比如一个人可以有多种状态, 开心, 生气, 郁闷... 那么在程序当中, 如何理解多态?我们就需要先明白以下几个概念: 1. 向上转型; 2. 重写; 才能理解多态. 1. 多态的概念 多态的概念通俗来说就是多种形态具体点就是去完成某个行为当不同的对象去完成时会产生出不同 的状态。 如下图, 不同的打印机打印出来的效果是不一样的; 再来看动物, 不同的动物吃的粮食是不一样的. 对象不一样, 而每一个对象有自己的行为, 那么行为就有可能不一样. 总的来说同一件事情发生在不同对象身上就会产生不同的结果。 2. 多态实现条件 在java中要实现多态必须要满足如下几个条件缺一不可 必须在继承体系下子类必须要对父类中方法进行重写通过父类的引用调用重写的方法 多态体现在代码运行时当传递不同类对象时会调用对应类中的方法。 3. 重写 重写(override)也称为覆盖。重写是子类对父类非静态、非private修饰非final修饰非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变核心重写重写的好处在于子类可以根据需要定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 【方法重写的规则】 子类在重写父类的方法时一般必须与父类方法原型一致 返回值类型 方法名 (参数列表) 要完全一致被重写的方法返回值类型可以不同但是必须是具有父子关系的访问权限不能比父类中被重写的方法的访问权限更低。例如如果父类方法被public修饰则子类中重写该方法就不能声明为 protected父类被static、private修饰的方法、构造方法都不能被重写。重写的方法, 可以使用 Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写. 我们来看下面的例子. class Animal {public String name;public int age;public Animal(String name, int age) {this.name name;this.age age;}public void eat() {System.out.println(name 吃饭);} }class Dog extends Animal {public boolean silly;public Dog(String name, int age, boolean silly) {super(name, age);this.silly silly;}Overridepublic void eat() {System.out.println(name 正在吃狗粮);} }public class Test {public static void main(String[] args) {Dog dog new Dog(hello, 10, false);dog.eat();} } 重写与重载的区别 重载: 方法名称相同;参数列表不同(数据类型, 顺序, 个数);返回值不做要求. 重写(一定发生在继承层次上): 方法名称相同;返回值相同(返回值构成父类子关系也可以);参数列表相同(数据类型, 个数, 顺序). 区别点 重写(override) 重载(override) 参数列表 一定不能修改 必须修改 返回类型 一定不能修改【除非可以构成父子类关系】 可以修改 访问限定符 一定不能做更严格的限制可以降低限制 可以修改 即方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。 【重写的设计原则】 对于已经投入使用的类尽量不要进行修改。最好的方式是重新定义一个新的类来重复利用其中共性的内容并且添加或者改动新的内容。 例如若干年前的手机只能打电话发短信来电显示只能显示号码而今天的手机在来电显示的时候不仅仅可以显示号码还可以显示头像地区等。在这个过程当中我们不应该在原来老的类上进行修改因为原来的类可能还在有用户使用正确做法是新建一个新手机的类对来电显示这个方法重写就好了这样就达到了我们当今的需求了。 静态绑定也称为前期绑定(早绑定)即在编译时根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。 public static void function() {}public static void function(int a) {}public static void function(int a, int b) {}public static void main(String[] args) {//编译的时候 根据你传入的参数 能够确定你调用哪个方法 这种就叫做 静态绑定function();function(1);function(1, 2);} 动态绑定也称为后期绑定(晚绑定)即在编译时不能确定方法的行为需要等到程序运行时才能够确定具体调用那个类的方法。 4. 向上转型和向下转型 4.1 向上转型 向上转型实际就是创建一个子类对象将其当成父类对象来使用。 Dog dog new Dog(hello, 10, false);//animal这个引用 指向了Dog对象Animal animal dog; 我们先把Dog类的eat()屏蔽掉, 然后执行以下的代码: public class Test {public static void main(String[] args) {Dog dog new Dog(hello, 10, false);Animal animal dog;animal.eat();} } 可以看到, 这里animal调用的eat是Animal本身的eat. 我们再在Animal中写入: public void function() {System.out.println(Animal::function()!);} 此时也是可以在main中访问到function的: animal.function(); 此时问题是, Animal能否调用Dog中的属性? 我们会发现是不能的, 编译器直接报错了. 因为Animal这个类就没有silly这个属性. 但是, 我们把前面屏蔽掉的Dog中重写的eat放开, 再执行animal.eat();打印的却是Dog的eat(). 为什么会出现上面的结果? 此时其实这里就是发生了动态绑定, 我们由代码可以知道, 这个eat(), Dog和Animal都有, 当子类没有的时候, 使用Animal的eat, 当子类有的时候, 我们发现在这个过程当中, animal.eat();调用的是子类的eat. 我们打开这个项目存在的路径: 找到这个运行程序的字节码文件, 来看一下它的反汇编代码: 在cmd窗口中输入javap -c Test以查看它的反汇编(一般情况下我们很少看反汇编代码), 可以看到是在哪里调用eat的: 可以看到, 编译的时候, 编译器认为调用的是Animal的eat(). 但是程序运行的时候, 变成了子类的eat. 我们把这么一个过程叫做: 动态绑定 那么于是我们就可以把上面的代码写成: Animal animal new Dog(hello, 10, false); // 向上转型语法格式 animal是父类类型但可以引用一个子类对象因为是从小范围向大范围的转换。 上面这种是直接赋值的向上转型的场景, 那么我们还有其他场景会发生向上转型, 就是方法传参和方法返回. 我们先来看方法传参. // 传进一个子类类型, 使用 Animal 接收public static void function2(Animal animal) {//..}public static void main(String[] args) {Dog dog new Dog(hello, 10, false);function2(dog);} 接下来我们在上面的代码中进行补充, 即: public static void function2(Animal animal) {animal.eat();} 然后写一个Cat类: class Cat extends Animal {public Cat(String name, int age) {super(name, age);}public void catchMouse() {System.out.println(name 抓老鼠);}Overridepublic void eat() {System.out.println(name 吃猫粮 );} } 在main中再补充: Cat cat new Cat(haha, 7);function2(cat); 那么现在站在function2()的角度下只有一个引用animal, 只去调用一个方法eat, 它去进行向上转型可以去引用Dog对象, 也可以引用Cat对象, 调用了两次function2, 当我们运行起来的时候(两个子类都重写了eat方法), 我们来看: 向上转型的优点让代码实现更简单灵活。 向上转型的缺陷不能调用到子类特有的方法。 向上转型的另一种形态: 方法返回 public static Animal function3() {return new Cat();} 4.2 向下转型 向下转型极度的不安全, 我们尽量不要去用向下转型. 将一个子类对象经过向上转型之后当成父类方法使用再无法调用子类的方法但有时候可能需要调用子类特有的方法此时将父类引用再还原为子类对象即可即向下转换。 那么它不安全在哪里? ClassCastException是类型转换异常, 报错内容: Dog不能转化为Cat. 所以我们就需要判断一下: public static void main(String[] args) {Animal animal2 new Dog(hello, 10, false);// 判断: animal2 是不是引用了 Cat这个对象if (animal2 instanceof Cat) {Cat cat (Cat) animal2;cat.catchMouse();}} 此时就不会报错了. 所以向下转型用的并不是很多. instanceof 关键字官方介绍: Chapter 15. Expressions (oracle.com) 5. 多态的优缺点 假设有如下代码: class Shape {public void draw() {System.out.println(画图形!);} }class Rect extends Shape {Overridepublic void draw() {System.out.println(画矩形!);} }class Cycle extends Shape {Overridepublic void draw() {System.out.println(画圆!);} }class Triangle extends Shape {Overridepublic void draw() {System.out.println(画一个三角形);} }class Flower extends Shape {Overridepublic void draw() {System.out.println(❀);} } public class Test {public static void drawMap(Shape shape) {shape.draw();}public static void main(String[] args) {Rect rect new Rect();drawMap(rect);drawMap(new Cycle());drawMap(new Triangle());drawMap(new Flower());} } 在drawMap()当中, Shape shape引用 引用的子类对象不一样, 调用方法表现出来的行为不一样. 我们把这种思想就叫做多态. 【使用多态的好处】 1. 能够降低代码的 圈复杂度, 避免使用大量的 if - else 什么叫 圈复杂度 ? 圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如果有很多的条件分支或者循环语句, 就认为理解起来更复杂. 因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 圈复杂度.如果一个方法的圈复杂度太高, 就需要考虑重构. 不同公司对于代码的圈复杂度的规范不一样. 一般不会超过 10 . 假设没有多态, 上面的代码写起来就会非常的麻烦. public class Test {public static void drawShapes() {// 假设没有多态, 就要用 if-else 去做String[] strings {cycle, rect, cycle, rect, flower}; // 先用字符数组存起来for (String x : strings) {// 通过大量的 if-else 去判断当前是什么, 就画什么.if (x.equals(cycle)) {Cycle cycle new Cycle();cycle.draw();} else if (x.equals(rect)) {Rect rect new Rect();rect.draw();} else {Flower flower new Flower();flower.draw();}}}public static void main(String[] args) {drawShapes();} } 如果使用使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单. public static void drawShapes() {Shape[] shapes {new Cycle(), new Rect(), new Cycle(), new Rect(), new Flower()};for (Shape s : shapes) {s.draw();}} 2. 可扩展能力更强 如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低. 对于类的调用者来说(drawShapes方法), 只要创建一个新类的实例就可以了, 改动成本很低. 而对于不用多态的情况, 就要把 drawShapes 中的 if - else 进行一定的修改, 改动成本更高. 多态缺陷代码的运行效率降低。 1. 属性没有多态性 当父类和子类都有同名属性的时候通过父类引用只能引用父类自己的成员属性 2. 构造方法没有多态性 6. 避免在构造方法中调用重写的方法 一段有坑的代码. 我们创建两个类, B 是父类, D 是子类. D 中重写 func 方法. 并且在 B 的构造方法中调用 func class B {public B() {func();}public void func() {System.out.println(B.func());} }class D extends B {private int num 1;Overridepublic void func() {System.out.println(D.func() num num);} }public class Test {public static void main(String[] args) {D d new D();} } 构造 D 对象的同时, 会调用 B 的构造方法.B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0. 如果具备多态性num的值应该是1.所以在构造函数内尽量避免使用实例方法除了final和private方法。 结论: 用尽量简单的方式使对象进入可工作状态, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题.
http://www.w-s-a.com/news/55363/

相关文章:

  • 没网站怎么做二维码扫描连接济南做网站推广哪家好
  • 台州建设规划局网站搞外贸一般是干什么的
  • 怎么提高自己网站的知名度电子商务是建网站
  • 官方查企业的网站办公用品网站建设策划书
  • 微信网站搭建哪家好网站中转页
  • 阿里巴巴网站开发是谁长沙自助模板建站
  • 阿里云网站方案建设书网络公司运营是干啥的
  • 南通seo网站排名优化nginx wordpress rewrite
  • 网站做成软件做内部网站费用
  • 浙江企业网站建设网站域名有了 网站如何建设
  • 学编程哪个机构有权威德州做网站优化
  • 最火的网站开发语言福州网站建设服务商
  • 嘉兴网站制作哪里好asp网站源码免费版
  • 如何给网站配置域名百度网站统计添加网址
  • 搭建wap网站磁力引擎
  • 如何给公司网站做推广个人网站可以做社区吗
  • 网站建设为什么不给源代码大理如何做百度的网站
  • 网站代理违法吗网站备份流程
  • 免费域名查询网站wordpress wordfence
  • h5响应式网站模板制作巴南网站制作
  • 网站方案报价软文什么意思
  • 电子商城网站如何建设上海公司车牌价格
  • 丽江网站设计公司专业公司网站设计企业
  • iis怎么建设网站特色产品推广方案
  • 道路建设网站专题品牌网站建设特色大蝌蚪
  • 网站开发组合 所有组合如何做com的网站
  • 电商网站怎么做的Wordpress 报表的插件
  • 纹理网站推荐买了两台服务器可以做网站吗
  • 机关公文写作网站南宁互联网推广
  • 五指山网站开发价格免费申请网站域名