面向对象、封装、继承、多态、JavaBean

news2024/11/16 3:52:10

二、面向对象

什么是对象

什么是对象?之前我们讲过,对象就是计算机中的虚拟物体。例如 System.out,System.in 等等。然而,要开发自己的应用程序,只有这些现成的对象还远远不够。需要我们自己来创建新的对象。

1. 抽取属性

代码里怎么表示类呢,看一下类的语法

class{
    字段;
    
    构造方法(参数) {
        
    }
    
    返回值类型 方法名(参数) {
        代码
    }
}
  • 字段定义与之前学过的局部变量、方法参数的定义类似,它们本质都是变量

  • 构造方法也是一种方法,在将来创建对象时被使用,作用是为对象字段赋初始值

    • 构造方法与类同名,不用加返回值类型声明
  • 从属于对象的方法不用 static 修饰,它就代表对象的行为,这里先放一下

例如:

public class Phone {
    // 类型 名字
    String brand; // 品牌
    String memory; // 内存
    String size; // 大小
    String color; // 颜色
    double price; // 价格

    public Phone(String b, String m, String s, String c, double p) {
        brand = b;
        memory = m;
        size = s;
        color = c;
        price = p;
    }
}

有了类,才能创建对象,创建对象的语法

new 类构造方法(参数)

例如

public class TestPhone {
    public static void main(String[] args) {
        Phone p1 = new Phone("苹果", "128G", "6.1寸", "星光色", 5799.0);
        Phone p2 = new Phone("红米", "4G", "6.53寸", "金色", 1249.0);
        Phone p3 = new Phone("华为", "4G", "6.3寸", "幻夜黑", 999.0);
        
        System.out.println(p1.color); // 获取p1的颜色
		System.out.println(p1.price); // 获取p1的价格
        
        p1.price = 3000.0;			  // 修改p1的价格
		System.out.println(p1.price); // 获取p1的价格
    }
}

总结一下:

  • 类是对象的模板,用字段描述对象将来长什么样,用构造给字段变量赋值
  • 对象说白了,就是一组数据的集合,但这些数据不是乱写的,有什么,不该有什么,得按类的规则来

2. 字段默认值

如果字段没有通过构造方法赋值,那么字段也会有个默认值

类型默认值说明
byte short int long char0
float double0.0
booleanfalse
其它null

比如说,想加一个字段 available 表示手机上架还是下架,这时就可以使用默认值统一设置

public class Phone {
    // 类型 名字
    String brand; // 品牌
    String memory; // 内存
    String size; // 大小
    String color; // 颜色
    double price; // 价格
    boolean available; // 是否上架

    public Phone(String b, String m, String s, String c, double p) {
        brand = b;
        memory = m;
        size = s;
        color = c;
        price = p;
    }
}
  • 构造方法里不对 available 字符赋值,默认为下架(false)
  • 要设置为默认上架(true)可以给字段直接赋值为 true 或在构造方法里给它赋值为 true

3. this

当方法参数与字段重名时,需要用在字段前面加 this 来区分

public class Phone {
    // 类型 名字
    String brand; // 品牌
    String memory; // 内存
    String size; // 大小
    String color; // 颜色
    double price; // 价格
    boolean available; // 是否上架

    public Phone(String brand, String memory, String size, String color, double price) {
        this.brand = brand;
        this.memory = memory;
        this.size = size;
        this.color = color;
        this.price = price;
        this.available = true;
    }
}
  • 前面有 this 的 brand 对应的是字段的 brand,前面没有 this 的 brand 对应的是方法参数中的 brand
  • this 代表对象自己,但只能在构造方法、对象方法中使用
  • 没有重名的情况下可以省略 this

提示

  • 如果觉得自己写 this 比较麻烦,可以使用 IDEA 的快捷键 ALT + Insert 来生成构造方法
  • 用 IDEA 生成的构造方法字段和方法参数都是用 this 区分好的

4. 无参构造

带参数的构造并不是必须的,也可以使用无参构造,例如

public class Student {
    String name;    // 姓名   null
    int age;        // 年龄   0

    Student() {

    }
}

使用无参构造创建对象示例如下

public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "张三";
        s1.age = 18;

        System.out.println(s1.name);
        System.out.println(s1.age);
    }
}
  • 字段赋值现在不是构造方法内完成了,而是先创建了对象
  • 再通过【对象.字段】来赋值,最终赋值效果是一样的

无参构造有个特性:

  • 默认提供一个无参构造,但是如果你书写了带参构造方法,此时默认的无参构造方法需要你重新书写

5. 对象方法演化

方法执行总得需要一些数据,以前我们学习的主要是这种 static 方法,它的数据全部来自于方法参数。

今天开始,要学习对象方法,顾名思义,它是从属于对象的方法,语法上要去掉 static,变成这个样子

public class Cal {

    double p;
    int m;
    double yr;

    public Cal(double p, int m, double yr) {
        this.p = p;
        this.m = m;
        this.yr = yr;
    }

    double cal() {
        double mr = yr / 100.0 / 12;
        double pow = Math.pow(1 + mr, m);
        return m * p * mr * pow / (pow - 1);
    }
}

看看改动成对象方法后,都有哪些代码发生了变化?为啥不需要参数了呢?

这种对象方法执行需要的数据:

  • 一部分来自于方法参数
  • 另一部分来自于方法从属的对象

既然我们讲的这种对象方法都从属于 Calculator 对象了,那么方法参数这里是不是就没必要再加一个 Calculator 对象了啊

方法体内这些本金、月份、利率,都来自于方法所从属的对象的字段。不用写前面的 c. 了

  • 当然,我们这个例子中,本金、月份、利率,在方法所从属的那个 Calculator 对象中已全部包含,因此方法上也无需更多其它参数。如果方法执行的有些数据,对象未包含,那你还是得添加方法参数

最后,方法调用时,为了表达与对象的这种从属关系,格式也应变化为:对象.方法()

public class TestCal {
    public static void main(String[] args) {
        // 对比相同本金,不同利率和贷款月份,计算总还款额(等额本息),看哪个更划算一些
        Cal c1 = new Cal(100000.0, 24, 4.5);
        double r1 = c1.cal();
        System.out.println("4.5% 利率借 2 年:" + r1);
        
        Cal c2 = new Cal(100000.0, 12, 6.0);
        double r2 = c2.cal();
        System.out.println("6.0% 利率借 1 年:" + r2);
    }
}

例如:

  • c1.cal() 执行时,cal 方法就知道,我执行需要的 y,m,yr 这些数据来自于 c1 对象
  • c2.cal() 执行时,cal 方法就知道,我执行需要的 y,m,yr 这些数据来自于 c2 对象

对象的方法演化完毕

静态方法 vs 对象方法

  • 而 static 方法需要的数据,全都来自于方法参数,它没有关联对象,没有对象的那一部分数据
  • 对象方法执行的数据,一部分数据从方法参数转移至对象内部

6. 静态变量

public class Circle {

    double r; // 半径
    static double pi = 3.14; // 静态变量, 所有圆对象共享它

    public Circle(double r) {
        this.r = r;
    }
    
    double area() {
        return pi * r * r;
    }
}

回到测试代码

public class TestCircle {
    public static void main(String[] args) {
        Circle c1 = new Circle(1.0);
        c1.pi = 3.14;
        Circle c2 = new Circle(1.0);
        c2.pi = 3;

        System.out.println(c1.area()); // 圆的面积计算结果为 3
        System.out.println(c2.area()); // 圆的面积计算结果为 3

    }
}

两次计算结果相同,因为 c1.pi 和 c2.pi 都是修改的同一个变量。注意几点

  1. 静态变量虽然也能通过对象来使用,但建议通过类名类使用,例如上例中,应该这么写Circle.pi = 3
  2. 如果不希望 pi 的值改来改去,可以再加一个 final 修饰符:static final pi = 3.14
    • final 加在变量上,表示该变量只能赋值一次,之后就不能修改了
  3. 最后要知道,计算如果需要更为精确的 pi 值,可以用 Math.PI ,上面我们自己写的 pi 只是为了举例需要

7. 四种变量

至今为止,一共学习了四种变量,下面就对它们做一个简单对比

public class TestVariable {
    public static void main(String[] args) {
        m(10);
        if (true) {
            C c1 = new C(30); // 出了if语句块,c1 对象就无法使用了,随带的它内部的对象变量也失效
        }
    }

    static void m(int a) {  // 1. 参数变量, 作用范围是从方法调用开始,直到方法调用结束
        for (int i = 0; i < 10; i++) {
            int b = 20; // 2. 局部变量, 作用范围从定义开始,到包围它的 } 为止, 必须赋初值才能使用
			System.out.println(b);
        }
    }
}

class C {
    int c;  // 3. 对象变量(成员变量)  从对象创建开始, 到对象不能使用为止

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

    static int d = 40; // 4. 静态变量, 从类加载开始, 到类卸载为止
}
  • 方法参数的作用范围就是从方法调用开始,直到这个方法结束为止,这是参数变量的作用范围
  • 局部变量的作用范围要更小一些,它是从局部变量定义开始,到包围它的 } 为止
    • 局部变量跟其它几个变量有个不一样的地方,它需要先赋值,再使用,否则会报错
  • 对象变量(其实就是对象中的字段)的作用范围是从对象创建开始,到对象不能使用为止,它的作用范围和对象是一样的
    • 对象变量是每个对象私有的
  • 静态变量,它的作用范围从类加载开始,到类卸载为止
    • 第一次用到这个类时,会把类的字节码加载到虚拟机里,这称之为类加载
    • 某个类以后不会再用到,类就会从虚拟机中卸载
    • 静态变量是所有对象共享的

三. 继承

1. 继承语法

阅读代码发现,这两个类中有一些相同的对象变量和方法代码,能否减少这两个类的重复代码,答案是继承

继承的语法

class 父类 {
    字段;
    方法() {}
}

class 子类 extends 父类 {
    
}

可以用父子类继承的方式减少重复声明,例如 A 是父类,B,C 类是子类,那么

class A {
    String name;
    void test() {}
}

class B extends A {
}

class C extends A {
}
  • 子类能从父类中继承它所声明的字段、方法

但注意,构造方法不能继承

  • 给父类加一个带参构造,发现子类都报错了,为什么呢?一方面构造方法不能继承
  • 另一方面对子类来说,你得调用父类的带参构造给父类的 name 字段赋值吧
  • 子类得先创建自己的构造方法,然后用 super 调用父类的带参构造,快捷键,alt+enter
class A {
    String name;
    A(String name) {
        this.name = name;
    }
    void test() {}
}

class B extends A {
    B(String name) {
        super(name);
    }
}

class C extends A {
    C(String name) {
        super(name);
    }
}
2. java 类型系统

java 中的类型分成了两大类

  • 基本类型 primitive type

    • 整数 byte short int long
    • 小数 float double
    • 字符 char
    • 布尔 boolean
  • 引用类型 reference type

    • 除了基本类型以外的其它类型都属于引用类型,引用类型可以看成是由基本类型组成的复杂类型,例如
      • String 内部由 byte[] 组成,而 byte[] 又是由 byte 组成
      • Phone 内部价格是 double,品牌等都是 String
    • 包装类型
      • 每个基本类型都有与之对应的包装类型,见下表
      • 包装类型是对象,既然是对象,就可以有对象的特征,如字段、方法、继承 …
    • null 值,不能对 null 值进一步使用(使用字段、调用方法),例如
      • String str = null;
      • str.length() 求字符串长度时,就会出现 NullPointerException 空指针异常
      • 使用引用类型之前,最好做非空判断,例如:if(str != null) 再做进一步操作
包装类型基本类型备注
Bytebyte
Shortshort
Integerint
Longlong
Floatfloat
Doubledouble
Characterchar
Booleanboolean
3. 类型转换
1) 基本类型转换

在这里插入图片描述

  • 整数和 char 7种类型
    • 顺箭头方向隐式转换
    • 逆箭头方向需要显式强制转换,可能会损失精度
  • boolean 类型无法与其它基本类型转换
  • short 与 char 也不能转换

隐式转换

byte a = 10;
int b = a; // 自动从 byte 转换为 int

强制转换

int c = 20;
byte d = (byte) c; // 在圆括号内加上要转换的目标类型

强制转换可能损失精度

int c = 1000;
byte d = (byte) c; // byte 的数字范围就是在 -128 ~ 127,存不下 1000,最后结果是 -24
2) 包装类型转换

在这里插入图片描述

  • 包装类型和它对应的基本类型之间可以自动转换,如
int a = 20;
Integer b = a;

Integer c = new Integer(30);
int d = c;
3) 引用类型转换
Java 继承的特点
  1. 单继承,子类只能继承一个父类
  2. Object 是所有其它类型直接或间接的父类型,定义 class 时,不写 extends 这个类也是继承自 Object
  3. 子类与父类、祖先类之间,可以用【是一个 is a】的关系来表达
向上向下转型

在这里插入图片描述

  • 顺箭头方向(向上)隐式转换,即子类可以用它的更高层的类型代表,表达一种是一个的关系

    • 例如一个猫对象,可以隐式转换为动物

      Animal a = new Cat(); // 用父类型的变量 a 代表了一只猫对象
      Object b = new Cat(); // 用祖先类型的变量 b 代表了一只猫对象
      
  • 逆箭头方向(向下)首先要符合是一个规则,然后用显式强制转换

    • 如果一个动物变量,它代表的是一个猫对象,可以通过强制转换还原成猫

      Animal a = new Cat();
      Cat c = (Cat) a;
      
    • 如果一个动物变量,它代表的是一个猫对象,即使强制转换,也不能变成狗,编译不报错,但运行就会出现 ClassCastException

      Animal a = new Cat();
      Dog d = (Dog) a;
      

为什么需要向上转型?主要是为了使用父类统一处理子类型

例1:

static void test(Animal a) {
    
}

这时,此方法既可以处理猫对象,也可以处理狗对象

test(new Cat());
test(new Dog());

例2:用父类型的数组,可以既装猫对象,也装狗对象

Animal[] as = new Animal[]{ new Cat(), new Dog() };
类型判断
Animal a = new Cat();

如果想知道变量 a 代表对象的实际类型,可以使用

System.out.println(a.getClass()); // 输出结果 class com.itheima.Cat
  • getClass() 是对象从 Object 类中继承的方法

如果想检查某个对象和类型之间是否符合【是一个】的关系,可以使用

Animals a = new Cat();
Object b = new Cat();

System.out.println(a instanceof Cat);   // true
System.out.println(a instanceof Dog);   // false
System.out.println(b instanceof Animal);// true

经常用在向下转型之前,符合是一个的关系,再做强制类型转换

4) 其它类型转换

除了以上转换规则,在赋值、方法调用时,一旦发现类型不一致,都会提示编译错误,需要使用一些转换方法才行

例如:两个字符串对象要转成整数做加法

String a = "1";
String b = "2";

System.out.println(a + b); // 这样不行,字符串相加结果会拼接为 12
System.out.println(Integer.parseInt(a) + Integer.parseInt(b)); // 转换后再相加,结果是 3

四. 多态

1. 何为多态

同一个方法在执行时,表现出了不同的行为,称这个方法有多态的特性。

2. 多态前提

不是所有方法都有多态,像之前写过的静态方法,不管怎么调用,表现出的行为都是一样的。那么要成为这种多态方法要满足哪些条件呢?先来看看多态这个词是怎么来的

多态,英文 polymorphism 本意是多种形态,是指执行一个相同的方法,最终效果不同。为什么会有这种效果?

方法虽然都是同一个,但调用它们的对象相同吗?看起来都是 Animal 啊,其实不是

  • 之前讲向上转型时讲过,子类对象可以向上转型,用父类型代表它
  • 这里的每个 Animal a 只是代表右侧对象,右侧的实际对象,是一些子类对象,大家应该都猜出来了,分别是猫、狗、猪
  • 这种有多态特性的方法在调用时,会根据实际的对象类型不同而行为不同
  • 而正是每个子类对象中的 say 方法写的不一样,从而表现出不同的叫声

方法具备多态性的两个条件:

条件1

用父类型代表子类对象,有了父类型才能代表多种子类型,只有子类型自己,那将来有多种可能吗,不行吧?

  • 比如说无论获取数组还是遍历,都使用猪类型,那最终也只能发出猪叫声,这是第一个前提条件
条件2

第二个条件,是子类和父类得有一个相同的 say 方法。如果子类存在与父类相同的方法,称发生了方法重写。重写方法要满足:

  1. 方法名和参数都完全相同
  2. 对象方法才能重写
  3. 检查是否发生了重写可以用 @Override 注解,它可以帮我们检查子类方法是否符合重写规则

只有重写了,才能表现出多种形态,如果没有重写,调用的都是父类方法,最终的效果是相同的,没有多态了

3. 贷款计算器 - 多态改造

在控制器代码中,需要用 if else 来判断使用哪个 Calculator 对象完成计算,Calculator0 还是 Calculator1,将来如果贷款类型越来越多,就要写好多 if else,如何避免呢?利用多态的原理,让 jvm 帮我们做判断

  • Animal a = … 利用多态,a 如果代表的是狗对象,走狗的逻辑,代表的是猫对象,走猫的逻辑
  • Calculator c = … 利用多态,c 如果代表的是等额本息对象,走等额本息逻辑,代表的是等额本金对象,走等额本金的计算逻辑
1) 产生方法重写

原来的

  • Calculator0 的方法叫 cal0 和 details0
  • Calculator1 的方法叫 cal1 和 details1
  • Calculator 父类中没有这俩方法

显然不行

改写如下:

class Calculator {
    // ...
    
    String[] cal() {
        return null;
    }
    
    String[][] details() {
        return null;
    }
}

class Calculator0 extends Calculator {
    Calculator0(double p, int m, double yr) {
        super(p, m, yr);
    }
	@Override
    String[] cal() {
        // ...
    }
	@Override
    String[][] details() {
        // ...
    }

}

class Calculator1 extends Calculator {
    Calculator1(double p, int m, double yr) {
        super(p, m, yr);
    }
	@Override
    String[] cal() {
        // ...
    }
	@Override
    String[][] details() {
        // ...
    }

}
2) 父类型代表子类对象

根据类型创建不同 Calculator 对象有点小技巧(避免了创建对象时的 if else),如下:

Calculator[] getCalculator(double p, int m, double yr) {
    return new Calculator[] {
        new Calculator0(p, m, yr),
        new Calculator1(p, m, yr)
    };
}

最后通过父类型来执行,表面上是调用 Calculator 父类的 cal() 和 details() 方法,但实际执行的是某个子类的 cal() 和 details() 方法,通过多态,避免了方法调用时的 if else 判断

@Controller
public class CalController {

    Calculator[] getCalculator(double p, int m, double yr) {
        return new Calculator[] {
            new Calculator0(p, m, yr),
            new Calculator1(p, m, yr)
        };
    }

    @RequestMapping("/cal")
    @ResponseBody
    String[] cal(double p, int m, double yr, int type) {
        Calculator[] cs = getCalculator(p, m, yr);
        return cs[type].cal();
    }

    @RequestMapping("/details")
    @ResponseBody
    String[][] details(double p, int m, double yr, int type) {
        Calculator[] cs = getCalculator(p, m, yr);
        return cs[type].details();
    }

}

cs[type] 是根据类型找到对应的子类对象,例如

  • type = 0 时,其实是获取了数组中索引 0 的对象,即 new Calculator0(p, m, yr)
  • type = 1 时,其实是获取了数组中索引 1 的对象,即 new Calculator1(p, m, yr)
3) 小结

关于多态的应用的例子讲完了,总结一下

前提

  • java 中的类型系统允许用父类型代表子类型对象,这是多态前提之一
  • 子类和父类之间发生了方法重写,这是多态前提之二

效果

  • 调用父类型的方法,可能会有不同的行为,取决于该方法是否发生了重写

什么时候使用多态

  • 多态能够用一个父类型,统一操作子类对象
  • 原本要根据类型做判断,写很多 if else 的地方,都可以考虑使用多态来消除 if else,提高扩展性

五. 封装

1.加强封装

Java 中可以用访问修饰符来对字段或方法进行访问权限控制,一共有四种

名称访问权限说明
public标识的【字段】及【方法】及【类】,谁都能使用
protected标识的【字段】及【方法】,只有同包类、或是子类内才能使用
标识的【字段】及【方法】及【类】,只有同包类才能使用默认访问修饰符
private标识的【字段】及【方法】只有本类才能使用(或内部类)
  • 类上能使用的访问修饰符,只有 public 和默认两种
private
package com.itheima.encapsulation;
public class Car {
	private int y; // 私有的
    private void test() { } // 私有的

    void update() {
        // 本类内可以使用
        System.out.println(this.y);
        this.test();
    }

}

package com.itheima.encapsulation; // 同包测试类
public class Test1 {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.y);  // 错误,不能访问 private 字段
        car.test();					// 错误,不能访问 private 方法
    }
}
默认
package com.itheima.encapsulation;
public class Car {
	int y; // 默认的
	void test() {} // 默认的

    void update() {
        // 本类内可以使用
        System.out.println(this.y);
        this.test();
    }

}

package com.itheima.encapsulation; // 同包测试类
public class Test2 {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.y);  // 同包可以使用
        car.test();					// 同包可以使用
    }
}

package com.itheima; // 不同包测试类
import com.itheima.encapsulation.Car;
public class Test3 {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.y);  // 错误,不同包不能访问 默认 字段
        car.test();					// 错误,不同包不能访问 默认 方法
    }
}
protected
package com.itheima.encapsulation;
public class Car {
	protected int y; // 受保护的
	protected void test() {} // 受保护的

    // 本类内可以使用
    void update() {
        System.out.println(this.y);
        this.test();
    }

}

package com.itheima; // 不同包子类
import com.itheima.encapsulation.Car;
public class SubCar extends Car {

    void display() {
        System.out.println(this.y); // 不同包子类内可以使用
        this.test();				// 不同包子类内可以使用
    }
}

尽可能让访问范围更小

  • private < 默认 < protected < public
  • 尤其是字段,建议设置为 private
  • 想让子类用 考虑设置为 protected

2. JavaBean

JavaBean 规范

  1. 字段私有, 提供公共 get、set、is 方法来访问私有字段
    • 获取字段值用 get 方法
    • 获取 boolean 类型字段值用 is 方法
    • 修改字段值用 set 方法
    • get、set、is 方法的命名必须是:getXXX,setXXX,isXXX
      • 其中 XXX 是字段名(首字母变大写)
      • 这些方法可以用 idea 的 ALT + Insert 快捷键生成
  2. 最好提供一个无参的构造
  3. 最好实现一个接口 Serializable

例子

class Teacher implements Serializable {
    private String name; // 小写
    private boolean married; // 已婚
    private int age;

    public boolean isMarried() { // 对 boolean 类型,用这种 isXXX
        return this.married;
    }

    public void setMarried(boolean married) {
        this.married = married;
    }

    // get 方法 用来获取私有字段值
    public String getName() { // get 后面单词首字母要大写
        return this.name;
    }

    // set 方法 用来修改私有字段值
    public void setName(String name) {
        this.name = name;
    }

    public Teacher(String name, boolean married) {
        this.name = name;
        this.married = married;
    }

    public Teacher() {
    }
}

测试类

public class TestJavaBean {
    public static void main(String[] args) {
        Teacher t = new Teacher("张老师", false);
        
        // 全部改用公共方法来间接读写字段值
        System.out.println(t.getName());
        System.out.println(t.isMarried());
        t.setMarried(true);
        System.out.println(t.isMarried());
    }
}

Java Bean 主要用来封装数据,不会提供哪些包含业务逻辑的方法

最后要区分两个名词:字段和属性

  • 有 getXXX、setXXX、isXXX 方法的,可以称该对象有 XXX 属性(首字母变小写)
    • 例如,上面的 Teacher 类有 name 属性和 married 属性
  • 没有对应 get、set、is 方法的,不能说有属性
    • 例如,上面的 Teacher 类没有 age 属性

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

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

相关文章

confluence模版注入漏洞_CVE-2023-22527

1. 漏洞简介 Confluence是Atlassian公司开发的一款专业的企业知识管理与协同软件&#xff0c;可用于构建企业wiki。 Confluence Data Center和Confluence Server多个受影响版本中存在模板注入漏洞&#xff0c;未经身份验证的威胁者可利用该漏洞在受影响的实例上实现远程代码执…

暗藏危险,警惕钓鱼邮件!

叮 您有一份福利待查收 您的信息资产需要排查 您的账户异常需要验证 这些看似“重要”的邮件 都藏着攻击者的恶意嘴脸 随着网络安全防护和建设的重要性日益凸显&#xff0c;国家安全、企业安全、合规需求及业务驱动等各个方面都亟需将网络安全作为基石。在企业业务转型发展…

v-on、事件修饰符、v-model、一些常用指令

v-on 事件修饰符 Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节&#xff0c;如&#xff1a;event.preventDefault() 或 event.stopPropagation()。 Vue.js 通过由点 . 表示的指令后缀来调用修饰符。 .stop - 阻止冒泡 .prevent - 阻止默认事件 .capture - 阻止捕获 .s…

【jetson笔记】解决vscode远程调试qt.qpa.xcb: could not connect to display报错

配置x11转发 jetson远程安装x11转发 安装Xming Xming下载 安装完成后打开安装目录C:\Program Files (x86)\Xming 用记事本打开X0.hosts文件&#xff0c;添加jetson IP地址 后续IP改变需要重新修改配置文件 localhost 192.168.107.57打开Xlaunch Win菜单搜索Xlaundch打开 一…

递归和尾递归(用C语言解斐波那契和阶乘问题)

很多人都对递归有了解&#xff0c;但是为尾递归很少&#xff0c;所以这次来专门讲一讲关于尾递归的一些问题。 什么是尾递归 如果一个函数中所有递归形式的调用都出现在函数的末尾&#xff0c;我们称这个递归函数是尾递归的。因为在一些题目的做法中&#xff0c;我们可以发现…

JavaFX场景入门

目录 JAVAFX jdk1.8以上引入javafx类库 JDK11JAVAFX(eclipse) 小知识点 舞台Stage platform、screen类 Scene场景类 查看电脑屏幕宽高 Group容器 JAVAFX项目 Image javafx场景 javaFx文本 javaFX颜色 JAVAFX jdk1.8以上引入javafx类库 JDK11JAVAFX(eclipse) 方式…

MySQL分组,获取组内最新的10条数据

一、记录 记录一次SQL&#xff0c;最近在项目中遇到了一个相对比较复杂的SQL。 要求依据分组&#xff0c;获取每个分组后的前10条数据。 分组查询最新的数据&#xff0c;应该都做过&#xff0c;但是获取前10条数据&#xff0c;还是没处理过的。 二、处理 2.1 前期数据准备 …

数据分析-Pandas如何用图把数据展示出来

数据分析-Pandas如何用图把数据展示出来 俗话说&#xff0c;一图胜千语&#xff0c;对人类而言一串数据很难立即洞察出什么&#xff0c;但如果展示图就能一眼看出来门道。数据整理后&#xff0c;如何画图&#xff0c;画出好的图在数据分析中成为关键的一环。 数据表&#xff…

【进入游戏行业选游戏特效还是技术美术?】

进入游戏行业选游戏特效还是技术美术&#xff1f; 游戏行业正处于蓬勃发展的黄金时期&#xff0c;科技的进步推动了游戏技术和视觉艺术的飞速革新。在这个创意和技术挑战交织的领域里&#xff0c;游戏特效和技术美术岗位成为了许多人追求的职业目标。 这两个岗位虽然紧密关联…

5.ROC-AUC机器学习模型性能的常用的评估指标

最近回顾机器学习基础知识部分的时候&#xff0c;看到了用于评估机器学习模型性能的ROC曲线。再次记录一下&#xff0c;想起之前学习的时候的茫然&#xff0c;希望这次可以更加清晰的了解这一指标。上课的时候听老师提起过&#xff0c;当时没有认真去看&#xff0c;所以这次可以…

硅像素传感器文献调研(八)

2000硅微带探测器的物理模拟&#xff1a;电极几何形状对临界电场的影响。 2000硅微带探测器的物理模拟&#xff1a;电极几何形状对临界电场的影响 摘要 本文介绍了交流耦合硅微带探测器的计算机分析。这项研究的目的是调查的主要几何参数负责潜在的关键影响&#xff0c;如早期…

【GitHub项目推荐--多功能 Steam 工具箱】【转载】

Steam 是一个开源跨平台的多功能 Steam 工具箱&#xff0c;此工具的大部分功能都是需要下载安装 Steam 才能使用。 功能包括网络加速、脚本配置、账号切换、库存管理、自动挂卡、游戏工具&#xff0c;比如强制游戏窗口使用无边框窗口化。 开源地址&#xff1a;https://github…

c++:类和对象(5),运算符重载

目录 运算符重载概念&#xff1a; 运算符重载 1.成员函数重载号 2.全局函数重载号 打印结果&#xff1a; <<运算符重载 递增运算符重载 简单例子 输出结果为&#xff1a; 赋值运算符重载 如何重载 输出结果为&#xff1a; 什么时候重载 关系运算符重载 简单例…

【并发编程】同步模式之保护性暂停

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳中求进&#xff0c;晒太阳 同步模式之保护性暂停 这个模式用到的基础就是wait-notify 详情可以看这篇文章》:【并发编程】wait/notify 即Guarded Suspension,用在一个线…

鸿蒙开发 状态管理

最近学习鸿蒙开发。 状态管理&#xff1a; State -> Prop 单向传递&#xff1b; stateprop: State -> Prop 单向传递 State -> Link 双向传递&#xff1b;

Windows脚本:监控并自动重启某个进程

Windows脚本&#xff1a;监控自动并重启某个进程 一、简介二 .bat脚本方式2.1 编制脚本2.2 创建并运行脚本2.3 设置关闭cmd窗口 三、使用VBScript脚本方式3.1 编制脚本3.2 运行脚本 四、设置脚本开机自启动五、某些软件加入启动项后&#xff0c;开机不会自动启动的解决方法 在实…

代码随想录算法训练营第十四天|二叉树基础-二叉树迭代-二叉树

文章目录 二叉树基础二叉树种类满二叉树完全二叉树二叉搜索树平衡二叉搜索树 二叉树的存储方式链式存储顺序存储 二叉树的遍历方式二叉树的定义 二叉树的递归遍历144.二叉树的前序遍历代码&#xff1a; 145.二叉树的后序遍历代码&#xff1a; 94. 二叉树的中序遍历代码 二叉树的…

Linux中并发程序设计

进程的创建和回收 进程概念 概念 程序 存放在磁盘上的指令和数据的有序集合&#xff08;文件&#xff09; 静态的 进程 执行一个程序所分配的资源的总称 动态的进程和程序比较 注&#xff1a;进程是存在RAM中&#xff0c;程序是存放在ROM(flash)中的进程内容 BSS段&#xff…

Unity通用渲染管线升级URP、HDRP

Unity通用渲染管线升级URP、HDRP 一、Build-in Pipline升级到 URP 一、Build-in Pipline升级到 URP 安装URP包 升级所有材质&#xff08;升级完成后材质会变成紫红色&#xff0c;Shader丢失&#xff0c;此为正常现象&#xff09; 创建 UniversalRenderPipelineAsset 配置文…

Origin:调整颜色刻度线间距和小数点

如何设置或修改Color Scale 的间距和小数位&#xff1f; 答&#xff1a;&#xff08;1&#xff09;更改间距&#xff1a;左键双击刻度标线——级别——“显示主刻度在”下选择自定义级别——在“值”输入自定义间距增量。 &#xff08;2&#xff09;更改小数点个数&#xff1a…