Day08-面向对象-继承

文章目录

  • 第7章 面向对象-继承
    • 1. 学习目标
    • 2. 继承
      • 2.1 继承的好处
      • 2.2 继承的语法
      • 2.3 继承的特点一:成员变量
        • 2.3.1 私有化(private)
        • 2.3.2 成员变量不重名
        • 2.3.3 成员变量重名
      • 2.4 继承的特点二:成员方法
        • 2.4.1 成员方法不重名
        • 2.4.2 成员方法重名——重写(Override)
        • 2.4.3 重写的应用
        • 2.4.4 注意事项
      • 2.5 继承的特点三:构造方法
        • 2.5.1 super的使用
        • 2.5.2 继承的常见写法
      • 2.6 继承特点
    • 3. this和super
      • 3. 2.this和super的使用格式
      • 3.3.避免子类和父类声明重名的成员变量
    • 4. 权限修饰符
    • 5. Object 类
      • 5.1 toString方法
      • 5.2 equals方法
      • 5.3 hashCode方法
      • 5.4 getClass方法
    • 6.native关键字
      • 6.1native的语法
    • 6.native关键字
      • 6.1native的语法

第7章 面向对象-继承

1. 学习目标

  • 能够实现类的继承,并说出继承的特点
  • 能够说出super关键字的作用
  • 能够说出Object类的常用方法
  • 能够说出Object类常见方法的用处并重写这些方法
  • 能够说出四种不同权限的区别
  • 能够说出native关键字的作用

2. 继承

继承是面向对象软件设计中的一个概念,与封装和多态共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

在这里插入图片描述

上述代码中,我们发现猫类和狗类具有很多共同的特征和行为,如果把这些相同的特征和行为再次抽象成为一个新的动物类,就可以将这个类定义为猫狗类的父类。

在这里插入图片描述

如上图中,猫狗类都可以称为子类,也叫派生类;多个类抽取出来的这个动物类称为父类超类(superclass)或者基类

继承描述的是事物之间的所属关系,这种关系是:is-a 的关系。例如,图中猫属于动物,狗也属于动物。可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系。

2.1 继承的好处

子类继承父类,就使得子类对象具有与父类相同的属性,可以调用父类相同的行为。

  • 提高代码的复用性
  • 提高代码的扩展性
  • 类与类之间产生了关系,是学习多态的前提

2.2 继承的语法

使用关键字extends来实现类之间的继承关系。

class 父类类名 {...
}class 子类类名 extends 父类类名 {...
}

继承演示,代码如下:

/** 定义动物类Animal,做为父类*/
class Animal {// 定义name属性public String name; // 定义age属性public int age;// 定义动物的吃东西方法public void eat() {System.out.println(age + "岁的" + name + "在吃东西");}
}/** 定义猫类Cat 继承 动物类Animal*/
class Cat extends Animal {// 定义一个猫抓老鼠的方法catchMousepublic void catchMouse() {System.out.println("抓老鼠");}
}/** 定义测试类*/
public class ExtendDemo01 {public static void main(String[] args) {// 创建一个猫类对象Cat cat = new Cat()// 为该猫类对象的name属性进行赋值cat.name = "Tom";// 为该猫类对象的age属性进行赋值cat.age = 2;// 调用该猫的catchMouse()方法cat.catchMouse();// 调用该猫继承来的eat()方法cat.eat();}
}演示结果:
抓老鼠
2岁的Tom在吃东西

2.3 继承的特点一:成员变量

2.3.1 私有化(private)
  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的公有方法进行访问。如图所示

在这里插入图片描述

/** 定义动物类Animal,做为父类*/
class Animal {// 定义name属性private String name; // 定义age属性public int age;// 定义动物的吃东西方法public void eat() {System.out.println(age + "岁的" + name + "在吃东西");}
}/** 定义猫类Cat 继承 动物类Animal*/
class Cat extends Animal {// 定义一个猫抓老鼠的方法catchMousepublic void catchMouse() {System.out.println("抓老鼠");}
}/** 定义测试类*/
public class ExtendDemo01 {public static void main(String[] args) {// 创建一个猫类对象Cat cat = new Cat();// 为该猫类对象的name属性进行赋值//cat.name = "Tom";// 编译报错// 为该猫类对象的age属性进行赋值cat.age = 2;// 调用该猫的catchMouse()方法cat.catchMouse();// 调用该猫继承来的eat()方法cat.eat();}
}

在这里插入图片描述

2.3.2 成员变量不重名

如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。代码如下:

class Fu {// Fu中的成员变量。int num01 = 3;
}class Zi extends Fu {// Zi中的成员变量int num02 = 4;// Zi中的成员方法public void show() {// 访问父类中的num,System.out.println("num1 = " + num1); // 访问子类中的num2System.out.println("num2 = " + num2);}
}class ExtendDemo02 {public static void main(String[] args) {// 创建子类对象Zi z = new Zi(); // 调用子类中的show方法z.show();  }
}演示结果:
num1 = 3
num2 = 4
2.3.3 成员变量重名

如果子类父类中出现重名的成员变量,这时的访问是有影响的。代码如下:

class Fu {// Fu中的成员变量。int num = 3;
}class Zi extends Fu {// Zi中的成员变量int num = 4;public void show() {// 访问的num到底是子类还是父类?System.out.println("num = " + num);}
}
class ExtendsDemo03 {public static void main(String[] args) {// 创建子类对象Zi z = new Zi(); // 调用子类中的show方法z.show(); }
}
演示结果:
num = 4

子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super 关键字,修饰父类成员变量,类似于之前学过的 this

使用格式:

super.父类成员变量名

子类方法需要修改,代码如下:

class Zi extends Fu {// Zi中的成员变量int num = 6;public void show() {//访问父类中的numSystem.out.println("Fu num=" + super.num);//访问子类中的numSystem.out.println("Zi num=" + this.num);}
}
演示结果:
Fu num = 5
Zi num = 6

小贴士:Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

2.4 继承的特点二:成员方法

当类之间产生了关系,其中各类中的成员方法,又产生了哪些影响呢?

2.4.1 成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。代码如下:

class Fu{public void show(){System.out.println("Fu类中的show方法执行");}
}
class Zi extends Fu{public void show2(){System.out.println("Zi类中的show2方法执行");}
}
public  class ExtendsDemo04{public static void main(String[] args) {Zi z = new Zi();//子类中没有show方法,但是可以找到父类方法去执行z.show(); z.show2();}
}
2.4.2 成员方法重名——重写(Override)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

  • 方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

代码如下:

class Fu {public void show() {System.out.println("Fu show");}
}
class Zi extends Fu {//子类重写了父类的show方法public void show() {System.out.println("Zi show");}
}
public class ExtendsDemo05{public static void main(String[] args) {Zi z = new Zi();// 子类中有show方法,只执行重写后的show方法z.show();  // Zi show}
}
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:创建的对象是谁,就优先用谁,如果没有则向上找。注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。
2.4.3 重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。比如新的手机增加来电显示头像的功能,代码如下:

class Phone {public void sendMessage(){System.out.println("发短信");}public void call(){System.out.println("打电话");}public void showNum(){System.out.println("来电显示号码");}
}//智能手机类
class NewPhone extends Phone {public void sendMessage(){System.out.println("发短信");System.out.println("发彩信");}
}public class ExtendsDemo06 {public static void main(String[] args) {// 创建子类对象NewPhone np = new NewPhone()// 调用父类继承而来的方法np.call();   // 调用子类重写的方法np.showNum();}
}

注意:这里重写时,用到super.父类成员方法,表示调用父类的成员方法。

2.4.4 注意事项
  1. 必须保证父子类之间方法的名称相同,参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

  2. 子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类)。

  3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > 缺省 > private
    备注:缺省不是汉字缺省,而是什么都不写,留空。

2.5 继承的特点三:构造方法

当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?

  1. 即便在子类的构造方法里没有手动使用super调用父类构造函数,子类也是会自动调用父类的空参数构造函数。

    class Animal {String name;int age;Animal() {System.out.println("不带参数的Animal被创建了");}Animal(String name,int age) {this.name = name;this.age = age;System.out.println("有参数的Animal被创建了!!!");}
    }class Dog extends Animal {Dog() {// super();   会自动调用父类的空参数构造方法System.out.println("不带参数的Dog被创建了");}Dog(String name,int age) {//super();  会自动调用父类的空参数构造方法this.name = name;this.age = age;System.out.println("有参数的Dog被创建了!!!");}
    }public class Test {public static void main(String[] args) {Dog dog1 = new Dog();// 调用输出结果:// 不带参数的Animal被创建了// 不带参数的Dog被创建了Dog dog2 = new Dog("jerry",2);//调用输出结果:// 不带参数的Animal被创建了// 有参数的Dog被创建了!!!}
    }
    
  2. 如果父类没有空参数构造方法,那么子类也不能有空参数构造方法。而且,子类的构造方法里必须要使用super手动调用父类指定的构造方法,不能再使用this.

    class Animal {String name;int age;Animal(String name, int age) {this.name = name;this.age = age;System.out.println("有参数的Animal被创建了!!!");}
    }class Dog extends Animal {// Dog(){} 父类没有空参数构造方法,子类也不能有空参数构造方法Dog(String name, int age) {// 子类构造方法里,不允许再使用 this,只能使用 super 调用父类的构造方法// 原因在于,子类每次在创建对象时,都会自动执行super()调用父类的空参数构造方法// super();  // 会自动调用父类的 super() 构造方法,但是此时父类没有空参数构造方法// this.name = name;// this.age = age;super(name, age);}
    }
    

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法。理解图解如下:

在这里插入图片描述

2.5.1 super的使用

super用于子类中,用来表示父类对象。使用super.可以调用父类的方法,访问父类的属性。

注意,如果直接写super()表示的是调用父类的构造方法,如果要使用super()调用父类构造方法,super()语句必须要写在子类构造方法的第一行。

class Animal {String name;int age;String color = "yellow";Animal(){}Animal(String name, int age) {this.name = name;this.age = age;System.out.println("有参数的Animal被创建了!!!");}public void demo() {System.out.println("我是Animal里的demo方法");}
}class Dog extends Animal {String type;Dog() {System.out.println("不带参数的Dog被创建了");}Dog(String name, int age, String type) {// 子类的实现方式和父类一致,可以直接使用super调用父类的方法 // this.name = name;// this.age = age;super(name, age);  // super()表示调用父类的构造方法,必须要写在子类构造方法的第一行this.type = type;}void showColor(){System.out.println(super.color);  // 可以调用父类里的属性super.demo();  // 也能够调用父类里的方法}
}public class Test {public static void main(String[] args) {Dog dog = new Dog("jerry", 2, "哈士奇");System.out.println(dog.type);dog.showColor();}
}

两种必须要使用super调用父类的构造方法的情况:

  1. 父类中没有空参数构造方法,此时子类的构造方法里必须使用super调用父类的构造方法。
  2. 父类的构造方法用到了私有变量,子类使用this无法访问到,需要使用super访问。
class Animal {private String name;private int age;Animal() {}Animal(String name, int age) {this.name = name;this.age = age;System.out.println("有参数的Animal被创建了!!!");}
}class Dog extends Animal {Dog() {}Dog(String name, int age) {// 父类的name和age属性私有,子类无法通过this访问到// this.name = name;// this.age = age;super(name, age);}
}public class Test {public static void main(String[] args) {Dog dog = new Dog("jerry", 2);}
}
2.5.2 继承的常见写法
class Animal {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}Animal(String name, int age) {this.name = name;this.age = age;}
}class Dog extends Animal {Dog(String name, int age) {super(name, age);}
}public class Test {public static void main(String[] args) {Dog dog = new Dog("jerry", 2);}
}

2.6 继承特点

  1. Java里只允许单继承,不允许多继承。

    class A{}
    class B{}
    class C extends A{}  // 正确
    class C extends A,B{}  // 错误,最多只能有一个父类
    
  2. Java里是允许多层继承(继承体系)的。

    class A{}
    class B extends A{}
    class C extends B{}
    
  3. 子父类只是一种相对概念。一个子类可以成为别的类的父类,一个父类也可以成为其他类的子类。

3. this和super

this:当前对象

  • 在构造器和非静态代码块中,表示正在new的对象
  • 在实例方法中,表示调用当前方法的对象

super:引用父类声明的成员

无论是this和super都是和对象有关的。

3. 2.this和super的使用格式

  • this
    • this.成员变量:表示当前对象的某个成员变量,而不是局部变量
    • this.成员方法:表示当前对象的某个成员方法,完全可以省略this.
    • this()或this(实参列表):调用另一个构造器协助当前对象的实例化,只能在构造器首行,只会找本类的构造器,找不到就报错
  • super
    • super.成员变量:表示当前对象的某个成员变量,该成员变量在父类中声明的
    • super.成员方法:表示当前对象的某个成员方法,该成员方法在父类中声明的
    • super()或super(实参列表):调用父类的构造器协助当前对象的实例化,只能在构造器首行,只会找直接父类的对应构造器,找不到就报错

3.3.避免子类和父类声明重名的成员变量

特别说明:应该避免子类声明和父类重名的成员变量

因为,子类会继承父类所有的成员变量,所以:

  • 如果重名的成员变量表示相同的意义,就无需重复声明

  • 如果重名的成员变量表示不同的意义,会引起歧义

在阿里的开发规范等文档中都做出明确说明:

在这里插入图片描述

4. 权限修饰符

在Java中提供了三种权限修饰符,四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限。

publicprotected缺省(什么都不写)private
同一类中
同一包中(子类与无关类)
不同包的子类
不同包中的无关类

可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。
  • 构造方法使用public ,方便创建对象。
  • 成员方法使用public ,方便调用方法。

5. Object 类

java.lang.Object类是Java语言中的根类,即所有类的父类。这个类里所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:

public class MyClass /*extends Object*/ {// ...
}
  • API(Application Programming Interface),应用程序编程接口。Java API是一本程序员的字典 ,是JDK中提供给我们使用的类的说明文档。所以我们可以通过查询API的方式,来学习Java提供的类,并得知如何使用它们。在API文档中是无法得知这些类具体是如何实现的,如果要查看具体实现代码,那么我们需要查看src源码

​ 根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个,今天我们主要学习其中的4个。

5.1 toString方法

方法签名:public String toString()

①默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

②通常是建议重写

③如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

因为Java的引用数据类型的变量中存储的实际上时对象的内存地址,但是Java对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM帮你调用了对象的toString()。

class Person {private int age;private String name;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {  // 重写了 toString 方法return "姓名:" + this.name + ",年龄:" + this.age;}
}
class Test {public static void main(String[] args) {Person p1 = new Person("张三", 18);// 当我们打印一个对象时,输出的结果就是这个对象 toString 方法的返回值System.out.println(p1);  // 姓名:张三,年龄:18}
}

通常情况下打印一个对象时,默认就是调用对象的toString()方法,如果这个对象没有重写toString()方法,会调用Object类的toString()方法。但是需要注意的是,打印 char 类型数组时,不会调用 char 类型数组的 toString() 方法。

注意:

char[] arr = [97,98,99];

System.out.println(arr);

System.out.println(arr.toString());

上述两段代码是有区别的。

5.2 equals方法

public boolean equals(Object obj):用于判断当前对象this与指定对象obj是否“相等”

①默认情况下,equals方法的实现等价于与“==”,比较的是对象的地址值

②我们可以选择重写,如果重写equals,那么一定要遵循如下几个原则:

  • 自反性:x.equals(x)返回true
  • 传递性:x.equals(y)为true, y.equals(z)为true,然后x.equals(z)也应该为true
  • 一致性:只要参与equals比较的属性值没有修改,那么无论何时调用结果应该一致
  • 对称性:x.equals(y)与y.equals(x)结果应该一样
  • 非空对象与null的equals一定是false
class Test {public static void main(String[] args) {Person p1 = new Person("张三", 18);Person p2 = new Person("张三", 18);System.out.println(p1 == p2);  // falseSystem.out.println(p1.equals(p2)); // true}
}class Person {private int age;private String name;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object obj) {return this.name == ((Person) obj).name && this.age == ((Person) obj).age;}
}

5.3 hashCode方法

public int hashCode():返回每个对象的hash值。

如果重写equals,那么通常会一起重写hashCode()方法,hashCode()方法主要是为了当对象存储到哈希表(后面集合章节学习)等容器中时提高存储和查询性能用的,这是因为关于hashCode有两个常规协定:

  • ①如果两个对象的hash值是不同的,那么这两个对象一定不相等;
  • ②如果两个对象的hash值是相同的,那么这两个对象不一定相等。

重写equals和hashCode方法时,要保证满足如下要求:

  • ①如果两个对象调用equals返回true,那么要求这两个对象的hashCode值一定是相等的;

  • ②如果两个对象的hashCode值不同的,那么要求这个两个对象调用equals方法一定是false;

  • ③如果两个对象的hashCode值相同的,那么这个两个对象调用equals可能是true,也可能是false

public static void main(String[] args) {System.out.println("Aa".hashCode());//2112System.out.println("BB".hashCode());//2112
}

5.4 getClass方法

public final Class<?> getClass():获取对象的运行时类型对象

因为Java有多态现象,所以一个引用数据类型的变量的编译时类型与运行时类型可能不一致,因此如果需要查看这个变量实际指向的对象的类型,需要用getClass()方法

public static void main(String[] args) {Object obj = new Person();System.out.println(obj.getClass());//运行时类型
}

6.native关键字

native:本地的,原生的

6.1native的语法

native只能修饰方法,表示这个方法的方法体代码不是用Java语言实现的,而是由C/C++语言编写的。但是对于Java程序员来说,可以当做Java的方法一样去正常调用它,或者子类重写它。

  public final native Class<?> getClass();

JVM内存的管理:

在这里插入图片描述

区域名称作用
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。

getClass()方法

public static void main(String[] args) {Object obj = new Person();System.out.println(obj.getClass());//运行时类型
}

6.native关键字

native:本地的,原生的

6.1native的语法

native只能修饰方法,表示这个方法的方法体代码不是用Java语言实现的,而是由C/C++语言编写的。但是对于Java程序员来说,可以当做Java的方法一样去正常调用它,或者子类重写它。

  public final native Class<?> getClass();

JVM内存的管理:

[外链图片转存中…(img-WO0JrVoY-1708569810512)]

区域名称作用
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电子器件系列63:焊带(光伏焊带)

光伏焊带&#xff0c;又称涂锡焊带。光伏焊带是光伏组件的重要组成部分&#xff0c;属于电气连接部件&#xff0c;应用于光伏电池片的串联或并联&#xff0c;发挥导电聚电的重要作用&#xff0c;以提升光伏组件的输出电压和功率。光伏焊带是光伏组件焊接过程中的重要材料&#…

[DP学习] 期望DP

一般思路 注&#xff1a;可以用方差求平方的期望 例题一 思路 重点&#xff1a;如何设状态&#xff0c;如何转移。 设状态 f[i] i 张能买到不同卡片的种类数的期望值&#xff08;直接对问题设置状态&#xff09; 状态转移&#xff1a;由于从f[i1]转移到 f[i] 时&#xff0…

【微服务生态】Elasticsearch

文章目录 一、概述二、下载和部署2.1 单机部署2.2 集群部署2.2.1 环境配置2.2.2 安装及部署 三、基本操作3.1 概述3.2 HTTP 操作3.2.1 索引操作3.2.2 文档操作3.2.3 关系映射3.2.4 高级查询 3.3 Java API 操作 四、Elasticsearch 进阶4.1 核心概念4.2 系统架构4.3 分布式集群4.…

利用nginx内部访问特性实现静态资源授权访问

在nginx中&#xff0c;将静态资源设为internal&#xff1b;然后将前端的静态资源地址改为指向后端&#xff0c;在后端的响应头部中写上静态资源地址。 近期客户对我们项目做安全性测评&#xff0c;暴露出一些安全性问题&#xff0c;其中一个是有些静态页面&#xff08;*.html&…

C 语言基本语法及实用案例分享

一、什么是 C 语言&#xff1f; C语言是一种较早的程序设计语言&#xff0c;诞生于1972年的贝尔实验室。1972 年&#xff0c;Dennis Ritchie 设计了C语言&#xff0c;它继承了B语言的许多思想&#xff0c;并加入了数据类型的概念及其他特性。C语言是一门面向过程的计算机编程语…

OpenCV笔记4:级联分类器实现嘴部检测

OpenCV 嘴部检测 """ 嘴部区域检测 1. 静态图像检测嘴部区域创建分类器加载特征文件检测图像绘制嘴部区域显示 2. 切换为摄像头 """ import cv2 import numpy as npclass FaceDetect:def __init__(self):# 级联分类器# 创建级联分类器&#xf…

js使用import到本js文件中的函数时报错 Error [ERR_MODULE_NOT_FOUND]: Cannot find module

node:internal/process/esm_loader:97internalBinding(errors).triggerUncaughtException(^Error [ERR_MODULE_NOT_FOUND]: Cannot find module D:\桌面\Pagesizedetection\lib\screensize imported from D:\桌面\Pagesizedetection\index.js Did you mean to import ../lib/sc…

Linux运维-DHCP服务器

DHCP服务器的配置与管理 项目场景 学校各部门共有180台电脑&#xff0c;除了计算机学院的教师会配置电脑的网络连接&#xff0c;其他部门的老师和工作人员均不会&#xff0c;为了提高网络的管理效率&#xff0c;技术人员决定配置一台DHCP服务器&#xff0c;来提供动态的IP地址…

啊丢的刷题记录手册

1.洛谷题P1923 求第k小的数 题目描述 输入 n&#xff08;1≤n<5000000 且 n 为奇数&#xff09;个数字ai​&#xff08;1≤ai​<109&#xff09;&#xff0c;输出这些数字的第 k 小的数。最小的数是第 0 小。 请尽量不要使用 nth_element 来写本题&#xff0c;因为本题…

2.23数据结构

单向循环链表 创建单向循环链表&#xff0c;创建节点 &#xff0c;头插&#xff0c;按位置插入&#xff0c;输出&#xff0c;尾删&#xff0c;按位置删除功能 //main.c #include "loop_list.h" int main() {loop_p Hcreate_head();insert_head(H,12);insert_head(…

知识图谱建立以及基于图谱的知识问答实战——以古诗文知识为例

最近比赛需要&#xff0c;所以特出一期建立知识图谱和相关知识问答的教程 整个过程需要用到工具Neo4j&#xff0c;这在我以前的博客中讲到怎么部署详情请看&#xff1a; Neo4j部署教程 如果想快速入门Neo4j请点击这里&#xff1a; Neo4j快速入门 此项目的github地址 参考的刘…

最简单的基于 FFmpeg 的视音频分离器 - 简化版

最简单的基于 FFmpeg 的视音频分离器 - 简化版 最简单的基于 FFmpeg 的视音频分离器 - 简化版正文结果工程文件下载参考链接 最简单的基于 FFmpeg 的视音频分离器 - 简化版 参考雷霄骅博士的文章&#xff0c;链接&#xff1a;最简单的基于FFmpeg的封装格式处理&#xff1a;视音…