图灵日记之java奇妙历险记--继承和多态

目录

  • 继承
    • 概念
    • 继承语法
    • 父类成员访问
      • 子类中访问父类的成员变量
      • 子类中访问父类的成员方法
    • super关键字
    • 子类构造方法
    • super和this
    • 初始化
    • protected关键字
    • 继承方式
    • final 关键字
    • 继承与组合
  • 多态
    • 条件
    • 向上转型
    • 重写
    • 动态绑定&&静态绑定
    • 多态再理解
    • 向下转型
    • 多态的优缺点
      • 好处
      • 缺陷

继承

class xiaoming {
    String name;
    int age;
    int height;
    String play;
}
class zhangsan {
    String name;
    int age;
    int height;
    String study;
}

上述代码,两个类有相同的部分,面向对象思想提出继承的概念,将共同点共性抽取,实现代码复用

概念

继承机制: 是面向对象程序设计使代码可以复用的最重要的手段,他允许程序员在保持类原有类特性的基础上进行拓展,增加新功能,这样产生的新的类,叫派生类.继承主要解决的问题是:共性抽取,实现代码复用

利用继承的思想,将上述代码共性部分进行抽取,达到共用
在这里插入图片描述

继承语法

在java中如果要表示类之间的继承关系,需要借助extends关键字
利用继承,可以将刚才的代码改写为

class stu {
    String name;
    int age;
    int height;
}

class xiaoming extends stu{
    String play;
}
class zhangsan extends stu{
    String study;
}

具体使用extends关键字如下:

修饰符 class 子类 extends 父类 {
// …
}

注意

子类会将父类中的成员变量或者成员方法继承到子类中了

父类成员访问

子类中访问父类的成员变量

在继承体系中,子类将父类中的方法和字段继承下来了
在子类方法中 或者 通过子类对象访问成员时:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

class stu {
    public String name;
    public int age;
    public int height;
}

class xiaoming extends stu{
    public String play;
    public void show(){
    //没有同名的情况
        System.out.println(name);
        System.out.println(age);
        System.out.println(height);
        System.out.println(play);
    }
}

如下代码:

class stu {
    private String name;
    public int age;
    public int height;
}

class xiaoming extends stu{
    public String play;
}

子类仍然可以继承这个父类的name变量,并获得该变量的存储空间。这并不是说子类可以直接访问该变量,但它在内部维护了对这个私有变量的引用。这意味着如果父类的这个私有变量发生改变,子类中的相应变量也会发生改变。

class big{
    public int a = 1;
}
class small extends big{
    public int a = 3;
    public void show(){
        System.out.println(a);
    }
}
public class test {
    public static void main(String[] args) {
        new small().show();
    }
}

在这里插入图片描述
照应上文,访问的成员变量与父类中成员变量同名,则优先访问自己的。

子类中访问父类的成员方法

成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时 再到父类中找,如果父类中也没有则报错
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用
方法适传递的参数选择合适的方法访问,如果没有则报错;

super关键字

class big{
    public int a = 1;
}
class small extends big{
    public int a = 3;
    public void show(){
        System.out.println(a);
    }
}

子类方法或变量与父类同名时,直接访问只会访问子类,要想访问父类就要用到super关键字,该关键字主要作用:在子类方法中访问父类的成员。

class small extends big{
    public int a = 3;
    public void show(){
        System.out.println(super.a);//访问父类
    }
}
public class test {
    public static void main(String[] args) {
        new small().show();
    }
}

在这里插入图片描述

class big{
    public int a = 1;
}
class small extends big{
    public int a = 3;
    public void show(){
        System.out.println(a);
        System.out.println(this.a);
        System.out.println(super.a);
    }
}
public class test {
    public static void main(String[] args) {
        new small().show();
    }
}

在这里插入图片描述

this包括父类和子类,依旧是先找子类再找父类

  1. 只能在非静态方法中使用
  2. 在子类方法中,访问父类的成员变量和方法。

子类构造方法

子类对象构造时,需要先调用基类(父类)构造方法,然后执行子类的构造方法
初始化父类要么就地初始化,要么默认初始化,或者调用构造方法

class cola{
    int c;
    public cola(int c) {
        this.c = c;
    }
}
class water extends cola{
    int a;
    int b;
}

如上代码,父类调用构造方法出现报错,为什么呢?在不创建构造方法的时候,会调用默认构造方法
(此处是默认构造方法的原代码)

-class cola{
    int c;
}
class water extends cola{
    int a;
    int b;
}

默认构造方法显式化如下:

-class cola{
    int c;
    public cola(){
    }
}
class water extends cola{
    int a;
    int b;
    public water(){
        super();
    }
}

或许会有宝子说子类构造方法不加super不是没有报异常吗,像这样

class cola{
    int c;
    public cola(){
    }
}
class water extends cola{
    int a;
    int b;
    public water(){
    }
}

这里还是把子类调用父类的构造方法给隐藏了,而非没有

class cola{
    int c;
    public cola(){
        System.out.println("父类构造方法");
    }
}
class water extends cola{
    int a;
    int b;
    public water(){
        super();
        System.out.println("子类构造方法");
    }
}

在这里插入图片描述
上述代码的结果可知,子类仍然会调用父类的构造方法
所以,现在我们可以解决一下这个报错的问题了

class cola{
    int c;
    public cola(int c) {
        this.c = c;
    }
}
class water extends cola{
    int a;
    int b;
}

父类的构造方法已经有了,不会调用默认构造方法但是子类的仍然会调用默认构造方法,如上代码的子类默认构造方法如下:

    public water(){
        super();
    }
}

此处super调用父类的默认构造方法就与已经实现的父类的构造方法不同,父类的构造方法如上上次代码可知是这样的

    public cola(int c) {
        this.c = c;
    }
}

默认构造方法有参数int c,但是super()并没有传参,所以不符,会报错异常

解决刚才的问题,如下解决:

class cola{
    int c;
    public cola(int c) {
        this.c = c;
    }
}
class water extends cola{
    int a;
    int b;
    public water(){
        super(1);//传参就ok了
    }
}
class cola{
    int c;
    public cola(int c) {
        this.c = c;
    }
}
class water extends cola{
    int a;
    int b;
    public water(int c){
    //调用父类的构造方法,帮助初始化子类从父类继承的成员,而不会去实例化父类对象
        super(c);
    }
}

子类对象中成员是由两部分组成的,父类继承下来的以及子类新增加的部分.构造子类对象时候,先调用父类的构造方法,先将父类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整
注意

  1. 若父类显示定义无参或者默认构造方法,在子类构造方法第一行默认隐含super()调用,即调用基类构造方法
  2. 如果父类构造方法含参,此时需要子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败
  3. 在子类构造方法中,super()调用父类构造时,必须是子类构造函数的第一天语句
  4. super()只能在子类构造方法中出现一次,并且不能和this同时出现

super和this

相同点

  1. 都是java中的关键字
  2. 只能在类的非静态方法中使用,用来访问非静态成员和字段
  3. 在构造方法中调用时,必须是构造方法中的第一天语句,并且不能同时存在

不同点
4. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于子类对象中从父类继承下来部分成员的引用
5. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
6. 在构造方法中:this()用于调用本类构造方法,super()用于调用父类构造方法,两种调用不能同时在构造方法中出现
7. 构造方法中一定会存在super()的调用,用户没有谢编译器也会自己000,但是this()用户不写则没有

初始化

class things{
    static {
        System.out.println("父类静态代码块");
    }
    {
        System.out.println("父类实例代码块");
    }
    things(){
        System.out.println("父类构造方法");
    }
    String name;
}
class building extends things{
    static {
        System.out.println("子类静态代码块");
    }
    {
        System.out.println("子类实例代码块");
    }
    building(){
        System.out.println("子类构造方法");
    }
    int height;
}
public class test {
    public static void main(String[] args) {
        building a = new building();
        System.out.println("=============");
        building b = new building();
    }

}

在这里插入图片描述
如上代码可得.静态代码块先执行且只执行一次,在类加载阶段执行,当对象创建时,才会执行实例代码块,实例代码块执行完后,最后调用构造方法,父类优先于子类,父类实例代码块和父类构造方法紧接执行,子类同理

protected关键字

在这里插入图片描述

package AA;

public class A {
    protected int a = 1;
}

package BB;

import AA.A;

public class B extends A{
    public static void main(String[] args) {
        A tem1 = new A();
        B tem2 = new B();
        System.out.println(tem2.a);    
        }
}

A类实例化出对象tem1,tem1无法访问是因为tem1是A的对象而非子类,protected修饰要满足之前图中的三个条件之一,tem2是B类的实例化对象,B类继承父类的成员,tem2实例化包括父类的成员,可直接访问

super不能在静态方法里使用,所以不能直接在main方法里使用super
利用如下代码来访问a

public class B extends A{
    public void show(){
        System.out.println(super.a);
    }
    public static void main(String[] args) {
        B tem = new B();
        tem.show();
    }
}

继承方式

单继承
多层继承
不同类继承同一个类
多继承(不支持)

java不支持多继承,不要出现超过三层的继承关系,如果想从语法上进行限制继承, 就可以使用 final 关键字

final 关键字

  1. 修饰变量或者字段,表示常量,不可改变
  2. 修饰类:表示此类不能被继承
  3. 修饰方法:表示该方法不能被重写

继承与组合

和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果。组合并没有涉及到特殊的语法,仅仅是将一个类的实例作为另一个类的字段

public class animal {
    public dog d;
    public cat c;
}

class dog{

}
class cat{

}

多态

条件

  1. 继承关系关系->向上转型
  2. 子类和父类有同名的覆盖/重写方法
  3. 通过父类对象的引用去调用这个重写的方法

多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法

在这里插入图片描述

向上转型

public class test extends test_big{
    public int b = 2;
    public test(int a, int b) {
        super(a);
        this.b = b;
    }
    public void func02(){
        System.out.println(b);
    }
    public static void main(String[] args) {
        test t01 = new test(1,2);
        test_big t02 = t01;
    }
}
class test_big{
    public int a = 1;
    public test_big(int a) {
        this.a = a;
    }
    public void func01(){
        System.out.println(a);
    }
}

如上代码,子类test和父类test_big,其中代码

    public static void main(String[] args) {
        test t01 = new test(1,2);
        test_big t02 = t01;
    }

实例化子类创建一个t01的对象,把t01的引用给父类对象,可以简化为

    public static void main(String[] args) {
        test_big t02 = new test(1,2);
    }

采用直接赋值的方式实现向上转型

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用
语法格式:父类类型 对象名 = new 子类类型()

    public static void fun04(test_big t) {
        return;
    }
    public static void main(String[] args) {
        test t = new test(1,2);
        fun04(t);
    }

如上:方法参数,传参的时候进行向上转型

如下返回值 向上转型

    public static test_big func03(test t){
        return t;
    }

再来看

test_big t = new test(1,2);

子类对象给到了父类对象的引用
t是父类对象,如果你用t调用子类成员还是不行,因为那是子类特有的

如果子类和父类同时共有一个方法,方法名,参数列表,返回值都相同的情况下,如下

public class test extends test_big{
    public void show(){
        System.out.println("子类show");
    }
    public static void main(String[] args) {
        test_big t = new test();
        t.show();
    }
}

class test_big{
    public void show(){
        System.out.println("父类show");
    }
}

子类和父类都有一样的show方法
子类:

    public void show(){
        System.out.println("子类show");
    }

父类:

    public void show(){
        System.out.println("父类show");
    }

在这里插入图片描述
可是t刚才不是说是父类对象吗,不能有子类的特性,这里却调用方法时,显示的是子类的方法

这里就要提到重写了,如果在继承关系上,满足方法的返回值一样,方法名一样,方法的参数列表一样,那就可以说这两个方法之间的关系是重写,而程序运行的时候绑定到了子类的show方法,这个过程叫作动态绑定

重写

//注解,提示
    @Override

实现重写:

  • 返回值,参数列表,方法名必须一样

  • 被重写的方法的访问修饰限定符在子类中必须大于等于父类的
    private 默认值 protected public

  • 被private修饰的方法是不可以被重写的

  • 被static修饰的方法是不可以被重写的

  • 被final修饰的方法是不可以被重写
    final修饰是常性的

  • 被重写的方法的返回类型可以不同,但是必须是具有父子关系的,如下,又被称为协变类型:

public class Animal {
    public Animal stay(){
        return null;
    }
}

class Dog extends Animal{
    public Dog stay(){
        return null;
    }
}

重写和重载的区别
参数列表:
重写一定不能修改,重载必须修改
返回类型:
重写一定不能修改,除非构成父子类关系,重载可以修改
访问修饰限定符:
一定不能做更严格的限制,可以降低限制,重载可以修改

public class Animal {
    @Override
    public String toString() {
        return "Animal{}";
    }
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog);
    }
}
class Dog extends Animal{
}

在这里插入图片描述
在这里插入图片描述

在Java中,Object 是所有类的直接或间接父类。每个类在Java都直接或间接地继承自Object类。这意味着,如果你创建一个类,而不明确指定它的父类,那么它将默认继承自Object类。
dog继承父类Animal,形参Dog类,实参Object类,向上转型,传参到valueOf方法,在valueOf方法里调用toString方法,因为子类Dog继承父类的toString方法,toString重写,obj调用子类的toString,打印Animal{}

动态绑定&&静态绑定

public class Animal {
    public void fun1(){
        System.out.println("父类");
    }
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.fun1();
    }
}
class Dog extends Animal{
    public void fun1(){
        System.out.println("子类");
    }
}

程序编译过程中,调用的是Animal的func1()
程序在运行过程中,调用Dog的func1方法
动态绑定->运行时绑定

静态绑定可以理解为在编译的时候已经确定要调用谁了

**静态绑定:**也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型确定了具体调用哪个方法.典型代表函数重载
**动态绑定:**也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能确定具体调用哪个类的方法

多态再理解


public class Animal {
    public String name;
    public void play(){
        System.out.println("动物正在玩");
    }
    public Animal(String name) {
        this.name = name;
    }
    public static void playAnimal(Animal animal){
        animal.play();
    }
    public static void main(String[] args) {
        Dog dog = new Dog("小狗");
        playAnimal(dog);
        Cat cat = new Cat("小猫");
        playAnimal(cat);
    }
}

class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }

    @Override
    public void play() {
        System.out.println(name+"正在玩");
    }
}
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
    @Override
    public void play() {
        System.out.println(name+"正在玩");
    }
}

在这里插入图片描述
当父类引用引用的子类对象不一样的时候,调用这个重写的方法,所表现出来的行为是不一样的,我们把这种思想叫作多态

向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。

 		Animal animal = new Dog("小狗");

这段代码向上转型可以理解为狗是一个动物,但是倒过来,动物不一定就是狗

 		Animal animal = new Dog("小狗");
        Dog dog = animal;

所以如上代码会报错,需要通过强转来实现

		Animal animal = new Dog("小狗");
        Dog dog = (Dog) animal;

向下转型并不安全

public class Animal {
    public String name;
    public void play(){
        System.out.println("动物正在玩");
    }
    public Animal(String name) {
        this.name = name;
    }
    public static void playAnimal(Animal animal){
        animal.play();
    }
    public static void main(String[] args) {
        Animal animal = new Dog("小狗");
        Cat cat = (Cat)animal;
        cat.speak();
    }
}

class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
    @Override
    public void play() {
        System.out.println(name+"正在玩");
    }
}
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
    public void speak(){
        System.out.println("喵喵");
    }
    @Override
    public void play() {
        System.out.println(name+"正在玩");
    }
}

在main方法里

    public static void main(String[] args) {
        Animal animal = new Dog("小狗");
        Cat cat = (Cat)animal;
        cat.speak();
    }

当你运行会发现运行失败
在这里插入图片描述
可以加一个限制防止出现这种情况

    public static void main(String[] args) {
        Animal animal = new Dog("小狗");
        //如果animal引用的对象是Cat对象的实例
        if(animal instanceof Cat){
            Cat cat = (Cat)animal;
            cat.speak();
        } else {
            System.out.println("here");
        }
    }

再次强调一下,向下转型非常不安全

多态的优缺点

好处

  1. 能够降低代码的圈“圈复杂度”,避免使用大量if-else
    圈复杂度是一种描述一段代码复杂程度的方式,一段代码如果平铺直叙,那么就比较容易理解,而如果有很多条件分支或循环语句,就认为理解起来更复杂
    因此我们可以见到粗暴的计算一段代码中条件语句和循环语句出现的个数,这个个数称为“圈复杂度”,如果一个方法的圈复杂度太高,就需要考虑重构
  2. 可扩展能力更强

缺陷

代码运行效率降低

  1. 属性没有多态性
    当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性
  2. 构造方法没有多态性
public class test {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}
class Dog extends Animal{
    public void eat(){
        System.out.println("dog");
    }
}
class Animal{
    public Animal(){
        eat();
    }
    public void eat(){
        System.out.println("Aniaml");
    }
}

如上代码,实例化Dog类创建对象dog,先调用父类的构造方法,父类Animal的构造方法里调用eat方法,eat方法在子类和父类都有的情况下,调用子类的eat方法,发生了动态绑定
稍微改动一下

class Dog extends Animal{
    private int d = 1;
    public void eat(){
        System.out.println("dog "+d);
    }
}

对Dog类作出以前的改动,打印出来是
在这里插入图片描述
打印出来是0,而不是1,因为现在实例化子类的时候先调用父类的构造方法,构造方法里可以调用子类和父类重写的方法,调用子类的eat方法,而此时的d变量还未被子类所初始化,属于默认值,int的默认值是0,所以打印出0

所以在构造方法里,尽量避免使用实例方法,除了final和private方法,因为final和private方法无法被初始化

总结:用尽量简单的方式使对象进入工作状态,尽量不要在构造器中调用方法,如果这个方法被子类重写,就会触发动态绑定,但是此时子类对象还没构造完成,可能会出现一些隐藏的极难发现的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/280073.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【逗老师的无线电】ICOM IC-705终端模式Terminal Mode直连反射器配置-外置Pi-Star网关篇

各位友台大家好呀,逗老师最近整了一台IC-705,最吸引人的莫过于这玩意可以通过USB连接树莓派直接进行通联。下面简单介绍一下这个功能和其配置方法 一、功能 终端模式Terminal Mode允许IC-705电台作为终端直接连接反射器,基于不同的连接方式…

C/C++学习笔记十三 C++中的重载运算符

1、什么是运算符重载? 运算符重载是 C 中的一项功能,使运算符(例如 、- 等)能够处理用户定义的数据类型。这种机制称为编译时多态性,并提供了为不同数据类型定制运算符行为的优点。 例如,我们可以重载“”运…

八皇后问题(C语言)

了解题意 在一个8x8的棋盘上放置8个皇后,使得任何两个皇后都不能处于同一行、同一列或同一斜线上。问有多少种方法可以放置这8个皇后? 解决这个问题的目标是找到所有符合要求的皇后摆放方式,通常使用回溯算法来求解。回溯算法会尝试所有可能…

网格布局(大练习)

最近对网格布局研究了一下,写了一个简单的demo。可以参考参考~ 网格基础布局:github地址 挤占网格布局:github地址 基础网站格局:github地址 复杂网站格局(方式一):github地址 复杂网站格局&am…

1.Linux快速入门

Linux快速入门 Linux操作系统简介Linux操作系统优点Linux操作系统发行版1. Red Hat Linux2. CentOS3. Ubuntu4. SUSE Linux5. Fedora Linux 32位与64位操作系统的区别Linux内核命名规则 Linux操作系统简介 Linux操作系统是基于UNIX以网络为核心的设计思想,是一个性…

X210 Linux开发板挂载NFS文件系统

网络搭建 采用“路由器”“有线网”来将Linux开发板和Ubuntu虚拟机连接在同一个局域网中。具体接线如下: Linux开发板通过网线直接连接到“路由器”的LAN接口上,然后笔记本电脑通过Wifi与路由器连接。 VirtualBox虚拟机网络设置 在”网线“设置界面中…

1.S32K3电源和复位

一、电源 S32K3系列芯片的电源各不相同。以S32K34x,S32K32x及S32K314为例。 并且该芯片支持以下特性: • Combination of internal and external voltage regulator options, offering RUN and Standby modes • FPM , which is used on chip-level in…

Flood Fill算法总结

算法思想 从一个起点开始,每一次随机选择一个新加进来的格子,看一下它周围能否扩展新的格子。如果能扩展,那么就扩展进来,直到不能扩展新的格子为止。当然需要判重,同样一个格子只能覆盖一次,这样能够保证时…

JVM工作原理与实战(二):字节码编辑器jclasslib

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、字节码编辑器jclasslib介绍和安装 1.介绍 2.安装 3.IntelliJ IDEA 插件安装 二、字节码编辑器jclasslib的使用 1.使用jclasslib bytecode viewer打开字节码文件 2.使用Intell…

gitLab页面打tag操作步骤

作者:moical 链接:gitLab页面打tag简单使用 - 掘金 (juejin.cn) 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 ---------------------------------------------------------------------…

对I2C总线上挂接多个AT24C02的读写操作

#include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ1 0xa1 // 器件1地址以及读取操作,0xa1即为1010 0001B #define OP_WRITE1 0xa0 // 器件1地址以…

python文件打包实战技巧

众所周知&#xff0c;python是一种脚本语言&#xff0c;python程序必须在python环境下运行&#xff0c;所以如果想把自己写的程序给别人看的话&#xff0c;就比较麻烦&#xff0c;他需要先配置python环境&#xff0c;对于电脑小白来说这是“要命”的事情。而且如果是客户的话&a…

ubuntu多用户环境dockerbug,卸载重装docker流程

之前不小心误操作删除重装docker&#xff0c;结果删除没成功&#xff0c;更没法重装&#xff0c;每次apt install都会报一个docker错误&#xff0c;虽然不影响软件的常规安装&#xff5e;但是现在还是需要装一个完整docker&#xff0c;还是选择删除一下&#xff0c;重点是关闭服…

多环境及SpringBoot项目部署

1、多环境 2、项目部署上线 原始前端 / 后端项目宝塔Linux容器容器平台 3、前后端联调 4、项目扩展和规划 多环境 程序员鱼皮-参考文章 本地开发&#xff1a;localhost&#xff08;127.0.0.1&#xff09; 多环境&#xff1a;指同一套项目代码在把不同的阶段需要根据实际…

共享单车之数据可视化

文章目录 第1关&#xff1a;绘制地图第2关&#xff1a;绘制流量最高的五条线路的路程图 第1关&#xff1a;绘制地图 任务描述 本关任务&#xff1a;使用JSP在百度地图上绘制一条共享单车起始路程。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何创建地…

macos下转换.dmg文件为 .iso .cdr文件的简单方法

为了让镜像文件在mac 和windows平台通用, 所以需要将.dmg格式的镜像文件转换为.iso文件, 转换方法也非常简单, 一行命令即可 hdiutil convert /path/to/example.dmg -format UDTO -o /path/to/example.iso 转换完成后的文件名称默认是 example.iso.cdr 这里直接将.cdr后缀删…

web一些实验代码—— JavaBean与EL标签

实验9&#xff1a; JavaBean与EL标签 使用javaBean和EL&#xff0c;完成注册和注册信息显示。 1、新建RegisterBean&#xff1b; package com.example.weeebbbb.the10;public class RegisterBean {private String user;private String pass;private String repass;private S…

【Transformer】深入理解Transformer模型2——深入认识理解(上)

前言 Transformer模型出自论文&#xff1a;《Attention is All You Need》 2017年 近年来&#xff0c;在自然语言处理领域和图像处理领域&#xff0c;Transformer模型都受到了极为广泛的关注&#xff0c;很多模型中都用到了Transformer或者是Transformer模型的变体&#xff0…

OCR在审核应用落地

本文字数&#xff1a;6686字 预计阅读时间&#xff1a;35分钟 01 背景 1、业务背景 在传统视频审核场景中&#xff0c;审核人员需要对进审视频中的文字内容进行逐一审核&#xff0c;避免在文字上出现敏感词、违禁词或者广告等相关词汇。这种人工审核费时费力&#xff0c;并且由…

【数据结构】双向带头循环链表的实现

前言&#xff1a;在前面我们学习了顺序表、单向链表&#xff0c;今天我们在单链表的基础上进一步来模拟实现一个带头双向链表。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:数据结构 &#x1f448; &#x1f4af;代码仓库:卫卫周大胖的…