JavaSE学习之--继承和多态

 

 💕"越是不思考的人,越不愿倾听别人说话。"💕

作者:Mylvzi 

 文章主要内容:JavaSE学习之--继承和多态 

目录

一.继承(inheritance)

1.为什么要有继承

2.继承的概念

3.继承的语法及代码实现 

4.在子类中访问父类成员-->super关键字

  1.子类中访问父类成员

11.不存在同名成员变量

1.2存在同名成员变量

1.3 那如何在子类中访问父类的成员呢?通过super关键字! 

1,4子类的构造方法

注意事项:

1.super只能放在第一行,放在其他行就报错

2.如果父类的构造方法带参数,则在子类中调用父类的构造方法时也要带参数!(可以快速创建)

3.在子类的构造方法中super和this不能同时出现,且super只能出现一次

1.5super和this的比较

5.再谈初始化

6.protected关键字

1.同一个包不同类中成员的访问

2.不同包不同类中成员的访问 

7.Java中的继承关系(三种)

8.final关键字

1.修饰变量会使变量不能被修改(成为常量)

2.修饰类,代表此类无法被继承 

3.修饰方法,此方法无法被重写 

9.继承与组合

二.多态

1.向上转型

1.向上转型的定义:

2.实现向上转型的三种方式

1.直接赋值

2.方法传参

3.方法返回

3.向上转型的优点:

4.向上转型的缺点:

2.向下转型:

3.动态绑定

4.方法重写

1.重写的规则:

2.重写与重载的区别:

5.多态

1.多态的优点:

1.降低圆圈复杂度

2.可拓展性强

2.多态的缺陷:代码运行效率低

3.多态的注意事项:


 

一.继承(inheritance)

1.为什么要有继承

    我们前面学过类,类是对现实事物的抽象化处理,而通过类实例化的对象则可以用来表示事物。在现实生活中,事物与事物之间有着千丝万缕的联系,最常见的一种就是“父子关系”,儿子会继承父亲的很多特征,而自己又有自己独特的特征;再比如狗和猫都是动物,都具有动物的一些属性,如年龄,性别,毛发颜色等等等等;为了在计算机中表示这种关系,创建了“继承”!

2.继承的概念

  继承(inheritance):就是对事物共性的抽取,从而实现代码复用;

从和实际生活的联系来讲,继承就是将事物的共同属性抽取出来,用一个大类来表示,比如一个父亲有多个孩子,这些孩子都具有某些共性,如年龄,性别,将这些共同属性抽取出来,创建一个新类“Child”;

从代码实现来讲,继承关系的存在实现了代码的复用,子类继承了父类的属性和方法,大大提高效率;

补充:

        其实Java中有很多这种“对共性进行抽取从而达到代码复用”的思路,比如前面学过的类变量,就是所有对象的共同属性的抽取 

对象的共性-->静态成员变量

类的共性-->继承extends

3.继承的语法及代码实现 

// 父类
class Animal {String name;int age;public void eat() {System.out.println(name+"i am eating!!!");}public void sleep() {System.out.println(name+"i am sleeping!!!");}
}// 子类
// 通过关键字extends表示此类继承于父类
class Dog extends Animal {public void bark() {System.out.println(name+"汪汪叫!!!");}
}class Cat extends Animal {public void mew() {System.out.println(name+"喵喵叫!!!");}
}
public class Test {public static void main(String[] args) {Dog dog1 = new Dog();dog1.name = "初一";dog1.age = 3;// dog1的成员变量中并没有name和age,但却能引用,则一定继承于父类System.out.println(dog1.name);System.out.println(dog1.age);dog1.eat();dog1.sleep();dog1.bark();}
}

总结:

1. 继承关键字-->extends,格式为:class 子类 extends 父类

2.子类会继承父类的成员和方法,实例化对象之后直接通过对象就能访问

3.子类继承父类的成员和方法之后,还需要有不同于父类的成员或方法(比如Dog类中的bark)

4.在子类中访问父类成员-->super关键字

  1.子类中访问父类成员

11.不存在同名成员变量

class Base {int a;int b;public void method1() {System.out.println("hello1");}
}class Derived extends Base {int c;// 类特有的public void method2() {a = 30;// 访问父类继承下来的变量b = 20;// 访问父类继承下来的变量c = 10;// 访问子类自己的变量}

1.2存在同名成员变量

class Base {int a;int b;public void method1() {System.out.println("hello1");}
}class Derived extends Base {int a;// 和父类同名int c;// 子类特有的public void method2() {a = 30;// 究竟是给父类赋值,还是给子类赋值?b = 20;c = 10;}

1.3在子类中访问成员方法

class Base {int a;int b;public void method1() {System.out.println("hello1");}
}class Derived extends Base {int c;// 和父类的方法构成了重载public void method1() {System.out.println("hello2");}// 子类特有的方法public void method2() {System.out.println("hello2");}
}
public class TestDemo1 {public static void main(String[] args) {Derived p1 = new Derived();p1.method1();p1.method2();// 输出hello1  hello2// 证明先执行子类的方法// 既不属于子类,又不属于父类,编译失败
//        p1.method3();}
}

总结:

        1.父类,子类存在同名的成员变量,成员方法,优先访问子类的,子类中没有再去父类中寻找,寻找不到就编译报错

        2.子类和父类可构成方法的重载,将参数列表设置为不同,在调用时通过传参调用不同的方法!

1.3 那如何在子类中访问父类的成员呢?通过super关键字! 

  由于设计不好或者特殊场景需要,需要在子类中访问父类成员,但如果出现重名编译器会优先访问子类中的,并不会访问父类中的成员变量,那该怎么解决呢?Java中提供了关键字super,该关键字的作用是-->在子类方法中访问父类成员变量

class Base {int a;int b;public void method1() {System.out.println("hello1");}
}class Derived extends Base {int a;int b;int c;public void method1() {a = 10;// 等价于this.ab = 20;// 等价于this.b// 通过super关键字来访问父类成员super.a = 30;super.b = 40;}

super访问方法: 

class Derived extends Base {int a;int b;int c;public void method1() {System.out.println("hello2 这是子类方法");}public void method2() {a = 10;// 等价于this.ab = 20;// 等价于this.b// 通过super关键字来访问父类成员super.a = 30;super.b = 40;method1();// 输出hello2super.method1();// 输出hello1

总结:

1.super关键字的作用就是在子类方法中访问父类成员变量和方法!

2.super只能在子类的非静态方法中使用,因为super主要用来访问并实例化父类中的实例变量,而实例变量必须依赖于对象,静态方法不依赖于对象,所以super不能在子类的静态方法中使用! (super可以访问父类的类变量,但是不建议,更建议通过类名)

3.super只是关键字,提升了代码的可读性,并不代表对父类成员的引用!

1,4子类的构造方法

  构造方法是用来初始化成员变量的一种特殊方法,其在对象的创建过程中就会被调用,而且即使你不写构造方法,编译器会默认添加一个不带参数的构造方法,给你的成员变量赋初始值;在子类中,既有从父类继承过来的成员变量,又有自己独有的成员变量,那在构造方法中赋值的顺序有没有要求呢?答案是有的,先上结论:
  必须先对父类成员变量进行初始化才能对子类成员变量进行初始化!

也就是说在子类的构造方法中会先调用对父类的构造方法,再对子类的成员变量进行初始化。

class Base {int a;int b;// 父类的构造方法public Base() {System.out.println("父类的构造方法!!!");}
}class Derived extends Base {int a;int b;int c;public Derived() {// 会默认有一个不带参数的super()// 代表父类的初始化System.out.println("子类的构造方法!!!");}
}

 

注意事项:

super()就代表调用父类的构造方法!!!

和this();的含义一样!!!

1.super只能放在第一行,放在其他行就报错

2.如果父类的构造方法带参数,则在子类中调用父类的构造方法时也要带参数!(可以快速创建)
    // 带参数的父类的构造方法public Base(int a, int b) {this.a = a;this.b = b;System.out.println("这是父类构造方法");}// 子类中的构造方法// 必须先对父类成员变量进行初始化public Derived(int a, int b, int a1, int b1, int c) {super(a, b);// 必须放在第一行// 且必须要传参数this.a = a1;this.b = b1;this.c = c;System.out.println("这是子类构造方法");}

注意:如果父类提供的是一个显式的构造方法,则在子类中必须利用super进行传参!!! 

如果父类的构造方法不带参数,在子类的构造方法中可以不写,因为系统会自动提供一个不带参数的super();

3.在子类的构造方法中super和this不能同时出现,且super只能出现一次

    在构造方法那一节我们学过,对于一个类的构造方法,如果要使用this来调用当前类的其他构造方法,则this只能放在第一行,那如果我既想通过super来初始化父类的成员变量,又想通过this调用当前类的其他构造方法该怎么办?答案是没有办法,如果同时拥有会冲突,只能保证他们不能同时存在!

  为什么只能出现一次呢?原因在于继承结构的逻辑链!在继承结构中,子类会先调用父类的构造方法,再执行自身的初始化逻辑,这种执行顺序是线性的,不需要多次进行父类的初始化!

 

1.5super和this的比较

  我们学过super和this,发现他们有很多相同点,比如都是通过.操作符来访问变量或方法,那他们有哪些异同点呢?下面来总结一下:

相同点:

1.都是Java中的关键字。

2.都只能在非静态方法中访问非静态成员变量或非静态方法

3.在构造方法中调用时,都必须写在第一行,所以super和this不能同时使用; 

不同点:

1.this代表当前对象的引用,用于访问当前对象的成员变量及方法;super是用来访问从父类继承的成员或方法。或者说super是引用对象从父类继承部分的引用

2.在构造方法中,super会有默认的对父类的构造方法(先有父后有子),而this并没有默认的构造方法。

3.this(......) 代表当前对象的构造方法,super(.......)代表父类的构造方法,两者不能同时出现

5.再谈初始化

  先回顾一下静态代码块,实例代码块,构造方法之间执行的先后顺序!

class Test {int a;// 构造方法public Test() {System.out.println("这是构造方法!!!");}// 静态块static {System.out.println("这是静态代码块!!!");}// 实例代码块{System.out.println("这是实例代码块!!!");}
}public class Test1 {public static void main(String[] args) {Test test1 = new Test();System.out.println("=============");Test test2= new Test();}
}

执行结果: 

 

总结:执行顺序-->静态代码块-->实例代码块-->构造方法 

且静态代码块只会被执行一次

那如果既有父类的代码块和构造方法,又有子类的代码块和构造方法,执行顺序是怎样的呢?

先看代码: 

class Test {int a;// 父类的构造方法public Test() {System.out.println("这是构造方法!!!");}// 父类的静态块static {System.out.println("这是静态代码块!!!");}// 父类的实例代码块{System.out.println("这是实例代码块!!!");}
}class DTest extends Test {// 子类的构造方法public DTest() {System.out.println("这是子类的构造方法!!!");}// 子类的静态代码块static {System.out.println("这是子类的静态代码块!!!");}// 子类的代码块{System.out.println("这是子类的代码块!!!");}
}public class Test1 {public static void main(String[] args) {DTest test1 = new DTest();System.out.println("=============");DTest test2= new DTest();}
}

执行结果:

执行顺序:

 1.父类,子类的静态代码块

2.父类实例代码块,构造方法

3.子类的实例代码块,构造方法

所有的静态代码块无论实例化多少个对象都只会被执行一次!!!

6.protected关键字

  为了实现封装特性,引入了访问修饰限定符,不同的关键字有不同的权限

  protected是“受保护的”,它的权限是可以在同包不同类访问,也可以在不同包但是此包的类是另一个包中类的子类,也就是两个包之间的类存在继承关系!

1.同一个包不同类中成员的访问

class B {private int a;int b;protected int c;public int d;
}class C extends B {// 同一个包不同类public void method() {super.a = 20;// err,private成员不能跨类访问super.b = 20;// 默认权限的成员可以跨类访问super.c = 20;// protected成员可以跨类访问super.d = 20;// public成员可以跨类访问}
}

2.不同包不同类中成员的访问 

class B {private int a;int b;protected int c;public int d;
}// 不同包但存在继承关系之间成员的访问
class C extends B {public void method2() {super.a = 20;// err private成员不能跨类访问super.b = 20;// err 默认权限成员不能跨包访问super.c = 20;// protected成员在子类中可以访问super.d = 20;// public成员可以跨包访问}
}

注意不要忘记引入父类的包:

总结:

1.继承是可以跨包的,如果另一个包中类是另一个包中的类的子类,则存在继承关系;子类会继承父类所有的成员和方法(但是不能全部访问,这取决于父类中成员或方法的访问权限)

2.我们有这么多的权限,那什么时候用什么权限呢?前期学习,大家都会使用一种粗暴的方法,把所有的成员设置为private,所有的方法设置为public,在前期对权限理解不深的时候我们可以这样设置,但使用哪个权限还是要具体问题具体分析,这取决于你对成员或方法的需求! 

7.Java中的继承关系(三种)

8.final关键字

  final关键字可以修饰变量,方法,类

1.修饰变量会使变量不能被修改(成为常量)

        final int b = 20;b = 30;// err b是常量,无法修改常量的值

2.修饰类,代表此类无法被继承 

final class B {private int a;int b;protected int c;public int d;
}// 此时B就无法被继承
class C extends B {
}

平常我们使用的String类就是被final修饰的

3.修饰方法,此方法无法被重写 

9.继承与组合

  继承反映的是类与类之间的关系,同样的,组合 也是一种反应类与类关系的一种思想!

它代表一个类可以由多个类组成,比如一个Person类可以由Leg,Nose,Head类组成,不同于继承的是组合并没有关键字,只需在类中包含其他类就可以实现类的组合,请看下面代码:

class Nose{};
class Head{};
class Leg{};class Person{private Nose nose;// 可以复用Nose类中的方法和属性private Head head;// 可以复用Head类中的方法和属性private Leg leg;// 可以复用Leg类中的方法和属性
}class Stu extends Person{// 继承了人的鼻子,头,腿
};

二.多态

多态就是通过父类引用不同对象,调用同一个重写的方法时,所表现的行为不同(所产生的结果不同),这种现象就叫做多态! 

要理解多态,需要理解几个基本概念:向上转型,重写,向下转型,动态绑定 

1.向上转型

1.向上转型的定义:

    父类引用引用子类对象就叫做向上转型(子类对象被父类引用)

class Animal{};
class Dog extends Animal{};
class Cat extends Animal{};
public class Test {public static void main(String[] args) {// 向上转型Animal animal1 = new Dog();Animal animal2 = new Cat();
}

2.实现向上转型的三种方式

1.直接赋值

2.方法传参

3.方法返回 

1.直接赋值

        Animal animal1 = new Dog();Animal animal2 = new Cat();

2.方法传参

    将方法形参设置为父类引用,实参是子类对象,通过调用方法实现将父类引用指向子类对象!

class Animal{public void makeSound() {System.out.println("动物发出叫声!");}
};
class Dog extends Animal{@Overridepublic void makeSound() {System.out.println("小狗在汪汪叫!");}
};
//class Cat extends Animal{};
public class Test {public static void animalMakeSound(Animal animal) {animal.makeSound();}public static void main(String[] args) {Animal mydog = new Dog();animalMakeSound(mydog);}

        在main方法中我们创建了一个Dog对象,并将其向上转型为Animal类型,接着在animalMakeSound方法中调用该对象,让父类引用指向该对象,在方法内部实现了向上转型!

    通过上述代码我们可以看出,将形参设置为父类引用最大的好处就是增加了代码的通用性!因为实参可以是任意子类对象

3.方法返回

    方法的返回类型可以是类 ,通过将方法的返回值设置为父类引用,让返回的对象被父类引用引用!!

// 父类
class Animal{public void eat() {System.out.println("eating");}
};class Cat extends Animal{String name;int age;public Cat(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println("cat is eating!");}
}
class Dog extends Animal{String name;int age;public Dog(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println("dog is eating!");}
};
//class Cat extends Animal{};
public class Test {public static void eat() {System.out.println("我在吃饭");}// 父类引用可以做返回值,还是让父类引用指向返回的对象public static Animal buyAnimal(String var) {if("狗".equals(var)) {return new Dog("小狗",2);} else if ("猫".equals(var)) {return new Cat("小米",20);}else {return null;}}public static void main(String[] args) {Animal animal1  =buyAnimal("狗");Animal animal2  =buyAnimal("猫");animal1.eat();animal2.eat();}

3.向上转型的优点:

1.实现代码的通用性,实现多态性

  通过父类引用子类对象,我们可以创建出更通用的代码,不需要去关注具体子类的类型

2.可以避免很多类型检查和强制类型转换

class Animal {public void makeSound() {};
}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵叫!");}
}class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("汪汪叫!");}
}public class Test1 {public static void main(String[] args) {Animal[] animals = new Animal[2];animals[0] = new Cat();animals[1] = new Dog();for (Animal animal: animals) {// 不适用向上转型// 需要进行类型检查和强制类型转换if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.makeSound();} else if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.makeSound();}}// 使用向上转型// 不需要关注具体的子类对象,代码更通用for (Animal animal2: animals) {animal2.makeSound();}}
}

对于这个代码,在 animals[0] = new Cat();实际上就发生了向上转型,animals[0]代表一个父类引用,new Cat()代表创建了一个新的Cat对象

4.向上转型的缺点:

无法使用子类特有的方法

 如果想通过父类引用去使用子类特有的方法,就要进行“向下转型”,也就是使父类引用发生强制类型转换!

2.向下转型:

    在很多时候子类有其特有的方法,而又不能通过重写来调用,这时候就需要通过向下转型来调用子类特有的方法,向下转型就是将父类引用强制类型转化为子类对象

class Animal{};
class Dog extends Animal{public void bark() {System.out.println("汪汪叫!");}
}
public class testdemo1 {public static void main(String[] args) {Animal animal1 = new Dog();// 向下转型Dog dog1 = (Dog)animal1;dog1.bark();// 输出汪汪叫!}
}

    但向下转型是一个很“危险”的操作,因为父类引用是一个较大的范围,你强制转化的类型是一个小范围,会出现意想不到的错误;同时,如果多个类继承于一个父类,要注意向下转型时不要转错类型!如果转换错误,编译器会报错:

所以,为了避免这种错误,需要利用关键字instanceof来检验当前引用所指向的类型 

class Animal{};
class Dog extends Animal{};
class Cat extends Animal{};
public class Test {public static void main(String[] args) {// 向上转型Animal animal1 = new Dog();// 父类引用            引用子类类型if(animal1 instanceof Dog) {// 利用instanceof运算符进行引用类型检查// 强制类型转化Dog dog = (Dog)animal1;System.out.println("类型检查成功");}else {System.out.println("ClassCastException!!!");}}
}

3.动态绑定

   动态绑定是面向对象编程非常重要的一个概念,也被叫做运行时绑定或运行多态性。他是指在运行时才确定对象的实际类型,并根据实际类型调用相应的方法,在通俗一点说就是只有在运行时我才知道引用的对象是谁,我该调用的方法是谁,这之前谁都不知道!!!

class Animal {public void makeSound() {};
}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵叫!");}
}class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("汪汪叫!");}
}public class Test1 {public static void main(String[] args) {Animal animal = new Dog();// 动态绑定animal.makeSound();// 实际调用的是Dog的方法  只有在运行时才知道实际对象是Dog}
}

4.方法重写

  重写(override):是子类对父类非static,final,private修饰,非构造方法的方法重写;通过重写,可以在子类内部实现属于子类的行为;

1.重写的规则:

1.被重写的父类方法不能被static,final,private修饰,不能是构造方法

2.重写的方法必须要和父类方法保持一致,即返回值,方法名,参数列表都要完全相同

3.子类的重写方法的权限要>=父类被重写方法的权限,比如父类方法的权限是public,那子类重写的方法就不能是protected!

4.子类中重写的方法可以被@Override 注解来显式指定,有了这个注解,可以多一层检验,比如父类的方法名是eat,而在子类中却写成ate,此时编译器就会报错(因为要求子类的方法名要和父类被重写方法的名称一致!)

2.重写与重载的区别:

重载是类方法多态性的体现,重写是子类与父类之间多态性的体现

方法重载是一种静态绑定,即在编译过程中就知道对应的方法(根据用户的传参)

方法重写是一种动态绑定,只有在运行时才能明确调用的方法 

5.多态

  再说回多态,以上内容都是为了理解多态而阐述的,所谓多态就是子类调用同一个父类方法时所产生的行为不同的思想,以下是多态的条件:

1.必须存在父类与子类的继承关系

2.必须有方法的重写

3.必须通过父类的引用来调用方法

多态的体现:在程序运行时,引用对象的不同,所产生的结果也不同!

1.多态的优点:

1.降低圆圈复杂度

  圆圈复杂度是反应一段代码理解难易程度的表示,如果一段代码平铺直叙,那他的圆圈复杂度就很低,此代码易于理解,但如果代码中含有大量的条件语句,循环语句,那么此代码的圆圈复杂度就很高,不易于理解(要判断的东西太多)

class Shape {public void drawMap() {};
}class Rect extends Shape {@Overridepublic void drawMap() {System.out.println("矩形");}
}class Flower extends Shape {@Overridepublic void drawMap() {System.out.println("❀");}
}class Cycle extends Shape {@Overridepublic void drawMap() {System.out.println("⚪");}
}public class Test2 {// 依次打印⚪矩形⚪矩形花public static void main(String[] args) {// 1.不使用多态  要判断子类的具体类型Rect rect = new Rect();Flower flower = new Flower();Cycle cycle = new Cycle();String[] shapes = {"cycle","rect","cycle","rect","flower"};for (String shape:shapes) {if(shape.equals("cycle")) {cycle.drawMap();} else if (shape.equals("rect")) {rect.drawMap();}else {flower.drawMap();}}// 2.使用多态Shape[] shapes = {new Cycle(),new Rect(),new Cycle(),new Rect(),new Flower()};for (Shape shape: shapes) {shape.drawMap();}}
}

 

2.可拓展性强

  比如对于shape类,现在有一个新的子类Triangle,可以直接新创建一个Triangle类,让其包含drawMap方法;如果不使用多态,则需要在打印时多添加一个if-else语句 

2.多态的缺陷:代码运行效率低

3.多态的注意事项:

1.属性不具有多态性,通过父类引用只能访问到父类的属性,而无法访问到子类的属性

2.构造方法没有多态性

先来看如下代码:


class B {public B() {
// do nothingfunc();}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);}
}
public class Test3 {public static void main(String[] args) {D d = new D();}
}// 执行结果:D.func() 0

  实例化d对象时,会先调用父类的构造方法,父类的构造方法中调用了func方法,此时会触发动态绑定,调用子类的func方法,而此时 private int num = 1;这段代码并未被执行,也就是说num还未被初始化,未被初始化则被赋值为0,所以打印:D.func() 0

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

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Linux多线程【线程互斥与同步】

✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌇前言🏙️正文1、资源共享问题1.1、多线程并发访问1.2、临界区与临界资源1.3、“锁” 概念引…

ESP8266使用记录(四)

放上最终效果 ESP8266&Unity游戏 整合放进了坏玩具车遥控器里 最终只使用了mpu6050的yaw数据,因为roll值漂移…… 使用了https://github.com/ElectronicCats/mpu6050 整个流程 ESP8266取MPU6050数据,处理后通过udp发送给Unity显示出来 MPU6050_Z…

【管理运筹学】第 5 章 | 整数规划(4,指派问题)

系列文章 【管理运筹学】第 5 章 | 整数规划 (1,问题提出与分支定界法) 【管理运筹学】第 5 章 | 整数规划 (2,割平面法及 0-1 变量的特性) 【管理运筹学】第 5 章 | 整数规划 (3,隐…

数据集笔记:上海摩拜共享单车

2017年8月上海地区摩拜单车的数据,已脱敏处理 订单id、自行车id、用户id、起始时间、起始经纬度、终止时间、终止经纬度、路径 数据地址: 链接:https://pan.baidu.com/s/1LqL_VtCfgm3vv-NrVCoTkw 提取码:3d3y

华为鸿蒙4,3,2禁用Google谷歌服务框架,使用最新谷歌Google play服务

华为鸿蒙4,鸿蒙3,鸿蒙2有一些应用或者游戏尤其是游戏需要最新版的谷歌play服务支持才可以使用。但是华为的鸿蒙系统解决完”设备未经 play 保护机制认证”之后,最稳定的谷歌play服务是20这个版本,一旦升级到最新的Google谷歌play服务,目前是最新版本23这…

区块链(6):p2p去中心化介绍

1 互联网中中心化的服务和去中心化服务的概念介绍 目前的互联网公司大都是中心化的 区块链网络大多是去中心化的 去中心化 2 p2p的简单介绍 java 网络编程:socket编程,netty编程,websoket简单介绍 2.1 节点是如何提供服务的(web编程实现)

MJ 种的摄影提示词关键字

景别 Front view photo 正面照 Front view photo of a Boston Terrier with smileSide view photo 侧身照 Side view photo of a Boston Terrier with smileBack view photo 背影照 Back view photo of a Boston TerrierFull body 全身照 Full body photo of a Boston Ter…

【Java 进阶篇】MySQL多表关系详解

MySQL是一种常用的关系型数据库管理系统,它允许我们创建多个表格,并通过各种方式将这些表格联系在一起。在实际的数据库设计和应用中,多表关系是非常常见的,它能够更好地组织和管理数据,实现数据的复杂查询和分析。本文…

Linux常见指令2

Linux常见指令[2] 一.Linux常见指令1.man补充知识:nano 2.cp3.mv4.cat补充知识:echo输出重定向追加重定向回到catcat其他用法 5.less和more补充内容回到less 6.head和tail补充知识:命令行管道 一.Linux常见指令 前言:为了方便我们在Linux中写指令 介绍一下: 1.clear指令: 清屏…

zemax埃尔弗目镜

可以认为是一种对称设计,在两个双胶合透镜之间增加一个双凹单透镜 将半视场增大到30,所有的轴外像差维持在可以接受的水平。 入瞳直径4mm波长0.51、0.56、0.61半视场30焦距27.9mm 镜头参数: 成像效果:

基于SpringBoot的教学资源库系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 社会的进步,教育行业发展迅速,人们对教育越来越重视,在当今网络普及的情况下,教学模式也开始逐渐网络化,各大…

Scala第二章节

Scala第二章节 scala总目录 章节目标 掌握变量, 字符串的定义和使用掌握数据类型的划分和数据类型转换的内容掌握键盘录入功能理解Scala中的常量, 标识符相关内容 1. 输出语句和分号 1.1 输出语句 方式一: 换行输出 格式: println(里边写你要打印到控制台的数据);方式二…

NSSCTF做题(4)

[NISACTF 2022]checkin 简单的一道代码审计了 但是发现传参传不上去 后来发现 在选中nisactf的时候,注释里面的内容也被标记了 不知道是为什么,把它复制到010里边去看看 发现了不对的地方 nisactf应该传参 根据这个进行url编码 我们选择实际的参名和…

用ChatGPT编写一个词卡显示网页

一、问题缘起 之前,我就发觉很多老师喜欢通过播放单词音频,显示单词拼写,这种词卡的形式来帮助学生记忆单词。于是,我就用Python制作了一个记单词软件,可以实现对words.txt中的单词滚动显示,播放发音&…

MySQL学习笔记23

逻辑备份: 1、回顾什么是逻辑备份? 逻辑备份就是把数据库、数据表或者数据进行导出,导出到一个文本文件中。 2、逻辑备份工具: mysqldump:提供全库级、数据库级别以及表级别的数据备份。 mysqldumpbinlog&#xff…

【Java 进阶篇】MySQL多表查询:内连接详解

MySQL是一种强大的关系型数据库管理系统,允许您在多个表之间执行复杂的查询操作。本文将重点介绍MySQL中的多表查询中的一种重要类型:内连接(INNER JOIN)。内连接用于检索满足两个或多个表之间关联条件的行,它能够帮助…

华为OD机试 - 快递业务站 - 并查集(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入:2、输出:3、说明: 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机…

MySQL 中的索引

文章目录 一、索引的创建二、聚簇索引与非聚簇索引三、联合索引和索引下推四、B 树索引 一、索引的创建 创建索引的方式包括两种: 隐式创建:数据库一般会在创建 PRIMARY KEY 和 UNIQUE 约束列时自动创建索引。显示创建:使用 CREAT INDEX 语…

全面解读 SQL 优化 - 统计信息

一、简介 数据库中的优化器(optimizer)是一个重要的组件,用于分析 SQL 查询语句,并生成执行计划。在生成执行计划时,优化器需要依赖数据库中的统计信息来估算查询的成本,从而选择最优的执行计划。以下是关…

基于PHP+MySQL的养老院管理系统

摘要 随着21世纪互联网时代的兴起,我们见证了人们生活方式的巨大改变。这个时代不仅深刻影响了我们的生活,还改变了我们对信息科学的看法。社会的各个领域都在不断发展,人们的思维也在不断进步,与此同时,信息的需求也与…