java篇 类的进阶0x0D:接口与抽象类

文章目录

  • 接口
    • 定位
    • 内容构成
      • 抽象方法
        • 缺省实现的抽象方法
        • private 方法
        • 静态方法
      • 静态常量
    • 应用特点
      • 多态
      • IDEA 快捷自动实现接口
    • 接口的继承
      • 接口是否属于多继承?
      • 从不同接口继承相同方法
      • 阻绝抽象方法的缺省实现
  • 抽象类
  • 抽象类 vs. 接口
    • 如何让接口更像抽象类

接口

定位

接口的本质是一种特殊的类,特殊在于接口仅仅是为了提供一种规范/标准。

内容构成

接口由一堆抽象方法(public abstract)和静态常量(public static final)组成。

// 接口1定义示例
public interface Expired{// 接口中的抽象方法(省略 public abstract)void sayHi();// 定义静态常量(省略 public static final)int expiredays = 365;                          
}// 接口2定义实例
public interface VirtualGoods {
}// 实现接口
public class Product implements Expired,VirtualGoods{}// 调用类
public class TestUse{public static void main(String[] args){Expired exp = new Product();}
}

抽象方法

接口里的方法(全都是抽象方法)都是 public abstract 修饰的,方法有名字、参数和返回值,但没有方法体,以分号结束。

因为接口里的方法都是(且只能)用 public abstract 修饰,所以这两个修饰符可以省略不写。

接口实际上是定义“标准”或者说“规范”(有哪些方法、方法签名、方法返回值类型),但不定义具体如何实现这些标准(方法体)。

由于方法没有方法体,所以建议给方法写好注释,说明定义这个方法的目的。

缺省实现的抽象方法

java 8 中,接口中开始允许有缺省实现的抽象方法。即可以在抽象方法中定义方法体,如果子类没有实现这个抽象方法,则以这个事先定义的“缺省”方法体作为这个抽象方法在子类中的具体实现。如果子类中对这个抽象方法进行了实现(覆盖),则无论抽象方法是否定义了“缺省”方法体,都以子类实现(覆盖)的方法体为准,作为具体实现。

// 接口中的抽象方法
void sayHi();// 等同于下面写法(也就是说 public abstract 可写可不写)
public abstract void sayHi();// 但如果定义缺省实现的抽象方法,就不能再写 abstract 了,语法是如下:
default void sayHi(){xxxx;
}// 或写成:
public default void sayHi(){xxxx;
}// 测试下方代码写法也正常运行:
default public void sayHi(){xxxx;
}// 但如果同时出现 default 和 abstract 那么无论怎么排列组合都会报错:java: 非法的修饰符组合: abstract和default
// public abstract default
// public default abstract
// default public abstract// 即,只要有 abstract 修饰,就不能有方法体。default 与 abstract 在接口中是无法同时出现的。

Kevin:我觉得这个 default 定义的所谓“抽象方法的缺省实现”,已经不能算是抽象方法了,它就仅仅是一个普通方法而已,看子类继承的时候要不要覆盖。

private 方法

java 9 中,接口中开始允许有 private 方法,当然这个 private 方法自然是只能服务于抽象方法的缺省实现了,否则也没有地方能用得上(若用在接口中的静态方法中显然也是不行的,因为静态方法中不允许调用非静态的方法,否则报错)。本质上,private 方法只是把抽象方法的缺省实现代码块中可以复用的一部分逻辑抽取出来而已。使用 private 方法是语法上允许了,但实际上真的不建议把接口中抽象方法的缺省实现搞得这么复杂。

优化代码

多说一句:其实实际上 java 在运行期间优化代码的时候,很多时候就是把 private 方法的代码拷贝/插入到调用这个 private 方法的地方,以减少一次方法的调用。(很多语言都是这样优化的)

静态方法

java 9 中,接口中还开始允许有静态方法(static)。静态方法可以被接口中的 public、private 方法调用,也可以在调用类中通过 接口名.静态方法名(参数列表) 调用,但在调用类中不能使用 实现了接口的子类的实例名.静态方法名(参数列表) 调用,(甚至不能用实现了接口的子类名.静态方法名(参数列表) 调用)否则会报错。这一点和普通类中的静态方法有明显区别。

另外,接口中的静态方法的访问修饰符只能是 public (可以省略不写,java 会默认是 public 的),不能定义为 protected、private 等其他的。

// 接口1
public interface Expired {// 抽象方法的缺省(默认)实现default boolean isDamaged() {boolean isDamaged = !qualityCondition();// describe();       // 可以在缺省实现方法体中调用 static 方法,正常执行。return isDamaged;}// private 方法private boolean qualityCondition() {// describe();       // 可以在 private 方法体中调用 static 方法,正常执行。return Math.random() < 0.5;}// 静态方法// 其实下方的静态方法也能写成 public static void describe(){ 但 IDEA 会提示 public 是多余的static void describe(){System.out.println("This is a method from Expired.");}}
// 接口2
public interface VirtualGoods {
}// 实现接口的类
public class Product implements Expired,VirtualGoods {	// 因为接口的抽象方法有默认实现,所以可以选择不覆盖此抽象方法
}// 调用类
public class TestUse {public static void main(String[] args) {Expired exp = new Product();System.out.println("当前商品损坏情况: " + exp.isDamaged());     // 当前商品损坏情况: true// exp.describe(); // 报错:java: 静态接口方法调用非法,应将接收方表达式替换为类型限定符 'org.test.interfacetest.Expired'Expired.describe();     // This is a method from Expired.// Product.describe();		// 报错。Product 类中找不到 describe 方法。IDEA 建议替换成 Expired 来调用。}
}

由于很多公司仍旧沿用 java 8,因此在设计时,尽量还是别在接口中定义 private 方法以及静态方法。

静态常量

接口里不能定义成员变量,定义的变量默认(且必须)都是 public static final 的(静态常量),这三个修饰符同样可以省略。

并且本身接口就不能实例化,定义成员变量也白搭,所以也没有这个需求。

// 接口的定义示例:/*** 这是一个过期商品的接口,可以检测这个商品是否在卖,大概还能在架上多少天*/
public interface Expired {/*** 返回当前在架情况** @return 是否在架*/boolean isOnSale();                  // 定义抽象方法/*** 根据过期时间计算还能在商品货架上放多少天** @param day   过期前剩余天数* @return      大概能再放多少天*/int saledays(int day);              // 定义抽象方法/*** 返回出厂设定的过期时间*/public abstract void expireday();       // 不会报错,但 IDEA 会提示建议你删除多余的 public abstract 修饰符public static final String brand = "Big Rabbit";      // 定义静态常量int expiredays = 365;                          // 定义静态常量(省略 public static final)}// 再定义一个完全没有任何抽象方法和静态常量的接口
public interface VirtualGoods {
}

应用特点

接口可以让一个类有多种类型,类似于多继承。即一个类可以同时 implements 多个接口。

接口无法被实例化。

// 接口的应用示例:
// 定义一个类来实现接口(需要覆盖接口中的所有抽象方法写出方法体,只要有抽象方法未被覆盖实现,都会报错)
public class Product implements Expired,VirtualGoods {@Overridepublic boolean isOnSale() {return true;}@Overridepublic int saledays(int day) {return (int)(day * 0.95);}@Overridepublic void expireday() {System.out.println("Total :"+expiredays);}
}// 调用类
public class TestUse {public static void main(String[] args) {Product candy = new Product();System.out.println(candy.isOnSale());           // trueSystem.out.println(candy.saledays(200));        // 190candy.expireday();                              // Total :365System.out.println(candy.expiredays);           // 365System.out.println(Product.expiredays);         // 365System.out.println(Expired.expiredays);         // 365System.out.println(candy.brand);                // Big RabbitSystem.out.println(Product.brand);              // Big RabbitSystem.out.println(Expired.brand);              // Big Rabbit}
}

注意在什么情况下使用接口。就比如说这个例子中,商品是否过期,可以作为一个接口被商品所实现。但如果说你定义的接口是 Animal(动物),再用 People(人类)去实现这个接口就很奇怪了,因为 Animal 和 People 更合理的是设计成一个类继承关系,而不是接口实现的方式。

多态

接口虽然不能实例化,但是可以用实现接口的类的引用/实例,给接口的引用赋值。类似于可以使用子类的引用/实例给父类引用赋值。

与类继承中存在的方法覆盖导致的多态一样,实现接口的不同类也会表现出这种多态现象。

因为毕竟接口本质上就是一种特殊的类,“实现某个接口”,其实和“继承某个类” 本质上没太大区别。

// 接口 1
public interface Expired {/*** 返回当前在架情况** @return 是否在架*/boolean isOnSale();                  // 定义抽象方法/*** 根据过期时间计算还能在商品货架上放多少天** @param day   过期前剩余天数* @return      大概能再放多少天*/int saledays(int day);              // 定义抽象方法/*** 返回出厂设定的过期时间*/public abstract void expireday();       // 不会报错,但 IDEA 会提示建议你删除多余的 public abstract 修饰符public static final String brand = "Big Rabbit";      // 定义静态常量int expiredays = 365;                          // 定义静态常量(省略 public static final)}// 接口 2
public interface VirtualGoods {
}// 实现接口的类 1 
public class Product implements Expired,VirtualGoods {@Overridepublic boolean isOnSale() {return true;}@Overridepublic int saledays(int day) {return (int)(day * 0.95);}@Overridepublic void expireday() {						// 注意这个方法的实现System.out.println("Total :"+expiredays);}
}// 实现接口的类 2
public class Goods implements Expired{@Overridepublic boolean isOnSale() {return false;}@Overridepublic int saledays(int day) {return 0;}@Overridepublic void expireday() {						// 注意这个方法的实现System.out.println("Never expire!");}
}// 调用类
public class TestUse {public static void main(String[] args) {Expired exp = new Product();Expired exp2 = new Goods();exp.expireday();                    // Total :365exp2.expireday();                   // Never expire!Product product = (Product) exp;VirtualGoods vir = (VirtualGoods) exp;		// 不报错,t
//        VirtualGoods vir2 = (VirtualGoods) exp2;    // 报错。无法将 Goods 转换成 VirtualGoods
//        Goods goods = (Goods)exp;       // 报错。无法将 Product 转换成 Goodsproduct.expireday();                // Total :365System.out.println(exp instanceof Product);         // trueSystem.out.println(exp2 instanceof Product);        // falseSystem.out.println(exp2 instanceof Goods);          // trueSystem.out.println(exp2 instanceof Expired);        // trueSystem.out.println(exp instanceof Expired);         // trueSystem.out.println(exp instanceof VirtualGoods);    // true}
}// 即关于子类实例给父类引用赋值、父类引用(实际指向子类实例)可以强制转换成子类后给子类引用复制。继承和接口实现的表现是一样的。

IDEA 快捷自动实现接口

可以借助 IDEA 快速实现接口的所有抽象方法。当然这个实现只是搭建出一个不报错的代码框架,里面的方法体内容还是需要我们根据业务逻辑去编写的。

public class Product implements Expired,VirtualGoods {}

将光标定位到接口处,按下 alt + enter ,在弹出的下拉框中点击 Implement methods,选中要自动实现的抽象方法,点击 OK 确认生成,就会得到如下代码框架,再根据需要自行编写代码。

public class Product implements Expired,VirtualGoods {@Overridepublic boolean isOnSale() {return false;}@Overridepublic int saledays(int day) {return 0;}@Overridepublic void expireday() {}
}

接口的继承

接口也可以继承接口。

接口可以继承多个接口,接口之间的继承也是用 extends

继承的接口,可以有重复的方法,但是签名相同时,返回值必须完全一样,否则会有编译错误。

  • 当然如果是方法名一样,但参数类型不一样(方法签名不完全相同)则是允许返回类型不同的(方法重载)。
public interface Intf1 {void m1();
}public interface Intf2 {int m1();void m2();
}public interface Intf3 extends Intf1,Intf2 {			// 报错,因为 Intf2 的 int m1() 与 Intf1 的 void m1() 冲突了(签名一样,返回值类型不一样,并且若定义为一个 double 另一个 int,仍然会报错,并不存在类型兼容的情形)void m3();
}

接口是否属于多继承?

接口虽然可以继承自多个接口,但和真正的多继承还是有区别的。因为接口本身没有成员变量,所以无论是类实现多个接口,还是接口继承自多个接口,都只能获得一堆方法(并且方法也是有限制的),而不会获得成员变量。这和多继承还是有区别的。

从不同接口继承相同方法

如果继承两个接口,两个接口里有同样的抽象方法,这是没有问题的。

但如果一个类实现了两个接口,并且两个接口里有相同的缺省方法,编译器会报错。

因为这样一来,java 也无法判别到底对于这个方法,是以哪个接口中的缺省方法作为方法体,所以报错。

  1. 从不同接口,继承相同的抽象方法(均无缺省实现)
public interface Intf1 {void m1();
}public interface Intf2 {void m1();
}public interface Intf3 extends Intf1,Intf2 {
}// 实现接口的类
public  class Test implements Intf3 {@Overridepublic void m1() {}
}// 调用类
public class TestUse extends Test{public static void main(String[] args) {Test a = new Test();					// 正常编译运行}
}
  1. 从不同接口,继承相同的抽象方法,其中一个有缺省实现。
// 实现接口的类不覆盖实现该抽象方法
public interface Intf1 {default void m1(){};
}
public interface Intf2 {void m1();
}
public interface Intf3 extends Intf1,Intf2 {}
public  class Test implements Intf3 {}
public class TestUse extends Test{public static void main(String[] args) {Test a = new Test();					// 报错。java: 类型 Intf1 和 Intf2 不兼容;接口 Intf3从类型 Intf1 和 Intf2 中继承了m1() 的抽象和默认值}
}// 要想不报错,做以下尝试:
// 1. 在接口中加入对抽象方法的覆盖实现
// 调用 Intf1 中的 default 方法
public interface Intf3 extends Intf1,Intf2 {@Overridedefault void m1() {Intf1.super.m1();// 若改为以下两种方式,会报错。// Intf1.m1();		// 报错:java: 无法从静态上下文中引用非静态 方法 m1()// 或// super.m1();		// 报错:找不到变量 super。}
}
// 或自己重新写一个方法覆盖
public interface Intf3 extends Intf1,Intf2 {@Overridedefault void m1() {// 留空也能正常运行}
}// 2. 不在 Intf3 中修改,而在 Test 对抽象方法进行实现覆盖。
public  class Test implements Intf3 {public void m1(){System.out.println("abc");}
}
// 实测,仍旧会报错:java: 类型 Intf1 和 Intf2 不兼容;接口 Intf3从类型 Intf1 和 Intf2 中继承了m1() 的抽象和默认值// 3. 在 Intf3 中重新声明为抽象方法,然后在 Test 中对抽象方法进行覆盖实现。
public interface Intf3 extends Intf1,Intf2 {void m1();
}
public  class Test implements Intf3 {@Overridepublic void m1() {// 留空也能正常运行}
}// 综上所述:
// 从不同接口中继承相同的抽象方法,其中一个有缺省实现,必须在发生继承冲突的节点(例子中是 Intf3 接口)处覆盖实现该抽象方法(可以在覆盖方法中调用有缺省方法体的那个接口的抽象方法,或重新声明为无缺省实现的抽象方法),否则报错。
  1. 从不同接口,继承相同的抽象方法,两个都有缺省实现。
// 缺省方法体实际内容相同
public interface Intf1 {default void m1(){};
}
public interface Intf2 {default void m1(){};
}
public interface Intf3 extends Intf1,Intf2 {}
public  class Test implements Intf3 {}
public class TestUse extends Test{public static void main(String[] args) {Test a = new Test();					// 报错。java: 类型 Intf1 和 Intf2 不兼容;接口 Intf3从类型 Intf1 和 Intf2 中继承了m1() 的抽象和默认值}
}// 要不报错,做以下尝试:
// 1. 在接口中加入对抽象方法的覆盖实现
// 调用 Intf1 中的 default 方法
public interface Intf3 extends Intf1,Intf2 {@Overridedefault void m1() {// Intf2.super.m1();		// 也是可以的。Intf1.super.m1();// 若改为以下两种方式,会报错。// Intf1.m1();		// 报错:java: 无法从静态上下文中引用非静态 方法 m1()// 或// super.m1();		// 报错:找不到变量 super。}
} 
// 或自己重新写一个方法覆盖
public interface Intf3 extends Intf1,Intf2 {@Overridedefault void m1() {// 留空也能正常运行}
}// 2. 不在 Intf3 中修改,而在 Test 对抽象方法进行实现覆盖。
public  class Test implements Intf3 {public void m1(){System.out.println("abc");}
}
// 实测,仍旧会报错:java: 类型 Intf1 和 Intf2 不兼容;接口 Intf3从类型 Intf1 和 Intf2 中继承了m1() 的抽象和默认值// 3. 在 Intf3 中重新声明为抽象方法,然后在 Test 中对抽象方法进行覆盖实现。
public interface Intf3 extends Intf1,Intf2 {void m1();
}
public  class Test implements Intf3 {@Overridepublic void m1() {// 留空也能正常运行}
}// 缺省方法体实际内容不同
public interface Intf1 {default void m1(){};
}
public interface Intf2 {default void m1(){System.out.println();};
}// 实测,和上面的情况一致,没有任何区别,都需要在 Intf3 中进行方法覆盖。// 综上所述:
// 从不同接口中继承相同的抽象方法,其中两个都有缺省实现(无论方法体中实际内容是否相同),必须在发生继承冲突的节点(例子中是 Intf3 接口)处覆盖实现该抽象方法(可以在覆盖方法中调用有缺省方法体的那个接口的抽象方法,或重新声明为无缺省实现的抽象方法),否则报错。

结论:当继承两个(或以上)接口,不同接口有相同的抽象方法(返回值类型相同+方法签名相同),只要其中有一个缺省实现的方法体(不论其他接口中是否也有缺省实现/缺省实现代码实际是否相同),就要在发生继承冲突(extends)的当前接口/发生实现冲突(implements)的当前类中覆盖该抽象方法(反正就是在继承发生交汇冲突的那个节点进行覆盖),否则报错。

  • 其中,这个在冲突交汇点的“覆盖”实现,其实还可以是重新去掉方法体,声明为不带缺省实现的抽象方法。

阻绝抽象方法的缺省实现

实现接口或用接口继承接口后,面对有缺省实现的抽象方法,可以有 3 种选择:

  1. 默默继承(extends)/实现(implements)这个抽象方法的缺省实现;

  2. 在当前类中覆盖实现该抽象方法(替代原本的缺省方法)/当前接口中重新用另一个缺省方法体覆盖父接口中的的缺省方法;

  3. 阻绝来自父接口的抽象方法缺省实现,将该方法重新定义为抽象方法。(如果当前是类而非接口,则需要把类定义为抽象类)。

    阻绝的目的是让后续的子类不会使用到之前定义的缺省方法体。

抽象类

抽象类可以看作是接口和类的混合体。用 abstract 修饰的类就是抽象类。

抽象类可以有抽象方法,也可以没有抽象方法,但不管包不包含抽象方法,抽象类都不能被实例化。

即便抽象类不含抽象方法,也是有实际意义的,因为有些类从设计(业务逻辑)来说,就不应该被实例化,而是用来被普通子类继承,再将子类实例化的。

抽象类可以继承别的类或抽象类,也可以实现接口。

抽象类中的抽象方法可以是自己定义的,也可以是继承自接口的。

  • 这里说的继承自接口不是说抽象类可以 extends 接口。只有接口才能 extends 接口,抽象类和其他类一样,只能 implements 接口。只不过抽象类可以 implements 接口之后不去将接口中的抽象方法实现(写出方法体),也就是实际上抽象类的确是继承了该接口的抽象方法。

接口可以实现类似“多继承”的效果,但抽象类和普通类一样,只允许类的单继承。

抽象类也可以被抽象类继承。

与接口不同,抽象类中不但可以定义非抽象方法(普通的方法),方法还可以是非 public 的,可以是任意的(protected、缺省、private)。

// 接口
public interface Battery {public static final double batteryAmount = 1000;public abstract double getBatteryAmount();String getBatteryBrand();
}// 抽象类
public abstract class Phone implements Battery {public String brand;protected String phoneCode = "ABC";						// 可以有非 public 属性protected abstract String getCountryOfOrigin();public void getCode() {									// 可以有非抽象方法。System.out.println("The phone code is: " + phoneCode);}
}// 普通类
public class Iphone extends Phone{String countryOfOrigin = "China";public Iphone(){this.brand = "Apple";}@Overridepublic double getBatteryAmount() {return batteryAmount;}@Overridepublic String getBatteryBrand() {String batterBrand = brand + ".battery.co";return batterBrand;}@Overrideprotected String getCountryOfOrigin() {return countryOfOrigin;}
}// 调用类
public class TestUse {public static void main(String[] args) {Iphone iphone = new Iphone();System.out.println(iphone.brand);                   // AppleSystem.out.println(iphone.countryOfOrigin);         // ChinaSystem.out.println(iphone.countryOfOrigin);         // Chinaiphone.getCode();                                   // The phone code is: ABCSystem.out.println(iphone.getBatteryAmount());      // 1000.0System.out.println(iphone.getBatteryBrand());       // Apple.battery.coPhone iphone2 = new Iphone();System.out.println(iphone2.brand);                  // AppleSystem.out.println(iphone2.getCountryOfOrigin());   // China// System.out.println(iphone2.countryOfOrigin);     // 报错。因为 Phone 类中是没有 countryOfOrigin 这个属性的。iphone2.getCode();                                  // The phone code is: ABCSystem.out.println(iphone2.getBatteryAmount());     // 1000.0System.out.println(iphone2.getBatteryBrand());      // Apple.battery.coIphone iphone3 = (Iphone) iphone2;System.out.println(iphone3.getBatteryBrand());      // Apple.battery.co}
}

抽象类 vs. 接口

其实接口从 java 8 抽象方法有了默认方法体,java 9 进一步有了 private 方法,就越来越像抽象类了,甚至你可以简单理解接口就是没有成员属性的抽象类。但接口本身定位是“制定规范”,所以业务逻辑的设计中,其实还是尽可能不要跑偏“制定规范”这个目的。

抽象类接口
被继承单继承被类多实现(implements)/被接口“多继承”(extends)
属性修饰符可以是任意的必须为 public static final(可以不写,不写也是这个)
方法修饰符可以是任意的必须为 public abstract(可以不写,不写也是这个)
实例化不能不能
引用被子类引用/子类实例赋值允许允许

如何让接口更像抽象类

因为接口和抽象类的一个很大区别就是接口是没有成员变量的,但接口其实最终是要被一个具体的类实现的,然后这个类可以有实例,实例就可以有属性。可以通过如下的思路设计,让接口更像一个抽象类。

// 接口
public interface Intf1 {String getName();		// 定义一个获取成员属性 name 的值的方法 default void sayHi(){System.out.println(getName() + " says 'hi!'");		// 通过 getName() 方法实现了类似成员属性的效果。// System.out.println(this.getName() + " says 'hi!'");       // 加不加 this 都行,这个this并不是指接口,而是实现接口的类的实例。所以虽然接口不能实例化,还是可以写 this 的。    }
}// 实现接口的类
public class Nor1 implements Intf1 {private String name = "Tom";@Overridepublic String getName() {		// 因为具体类是要覆盖抽象类的所有抽象方法的,所以一定会覆盖到这个方法return this.name;}
}// 那么现在对于接口来说,其实就可以通过调用方法来实现类似“拥有成员变量”的效果的// 调用类
public class TestUse {public static void main(String[] args) {Intf1 a = new Nor1();System.out.println(a.getName());			// Tom// System.out.println(a.name);				// 报错。而且即便声明  Nor1 a = Nor1(), name 在 Nor1 类中也是 private 的。a.sayHi();									// Tom says 'hi!'}
}

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

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

相关文章

Apple - Bonjour (NSNetService)

Bonjour 文章目录 Bonjour一、Bonjour介绍Cocoa 网络框架二、Bonjour 网络配置原理1. 寻址(分配IP地址给主机)2. 命名 (使用名字,而不是IP地址来代表主机)3. 服务搜索(自动在网络搜索服务)三、使用说明1、发布服务2、查询服务3、决议服务四、使用示例NSNetServiceBrowserD…

Maven项目的两种打包方式-spring-boot-mavne-plugin/maven-jar-plugin

Maven项目的两种打包方式-spring-boot-mavne-plugin/maven-jar-plugin 1. 前言Maven的两种打包方式 2. 流程图3. spring-boor-maven-plugin打包4. maven-jar-plugin/maven-dependency-plugin打包 1. 前言 Maven的两种打包方式 spring-boot-maven-plugin springboot默认打包方…

如何运用R语言进行Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合实践与拓展

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

Simple Set Problem hdu 7314

Problem - 7314 题目大意&#xff1a;有n个数组&#xff0c;从每个数组中取一个数构成数组b&#xff0c;求b中最大值和最小值的差的最小值 1<n<1e6;总数字数量<1e6;-1e9<数字大小<1e9 思路&#xff1a;要想最大值和最大值的差最小&#xff0c;所以我们要对他…

【FusionInsight HD】FusionInsight HD 651创建集群-Yarn

FusionInsight HD 651创建集群-Yarn FusionInsight HD 651创建集群-Yarn登录FusionInsight Manager修改初始密码创建集群设置集群信息选择主机设置机架选择服务分配角色服务配置确定安装集群集群验证HDFS验证Yarn验证Zookeeper验证总结FusionInsight HD 651创建集群-Yarn 登录…

机器学习深度学习——softmax回归的简洁实现

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——softmax回归从零开始实现 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你…

Java 设计模式——原型模式

目录 1.概述2.结构3.实现3.1.浅拷贝3.2.深拷贝3.2.1.通过对象序列化实现深拷贝&#xff08;推荐&#xff09;3.2.2.重写 clone() 方法来实现深拷贝 4.优缺点5.使用场景 1.概述 &#xff08;1&#xff09;原型模式 (Prototype Pattern) 是一种创建型设计模式&#xff0c;是通过…

在Windows 10/11 上安装GNS3模拟器

文章目录 在Windows 10/11 上安装GNS3模拟器简介支持的操作系统最低要求推荐配置要求最佳配置要求下载GNS3 all-in-one 安装文件安装GNS3在Windows 10/11 上安装GNS3模拟器 简介 本文档解释了如何在Windows环境中安装GNS3。你将学习如何: 下载所需的软件安装前提条件和可选软…

【C++】 VS2020 vector+template的案例

如果对博主其他文章感兴趣可以通过【CSDN文章】博客文章索引找到。 # include <iostream> # include <vector> using namespace std;template<class T> // 用class或者typename均可 void my_print(T& v, const string msg) // v前面不允许加const, 加…

SpiderFlow爬虫平台(爬虫学习)

申明 作为自己学习的记录,方面后期查阅 官网 SpiderFlow官网 简介 spider-flow 是一个爬虫平台&#xff0c;以图形化方式定义爬虫流程&#xff0c;无需代码即可实现一个爬虫 是使用springboot开发的项目,后端代码直接运行即可使用

Codeforces Round 888 (Div. 3)(A-F)

文章目录 ABCDEF A 题意&#xff1a; 就是有一个m步的楼梯。每一层都有k厘米高&#xff0c;现在A的身高是H&#xff0c;给了你n个人的身高问有多少个人与A站在不同层的楼梯高度相同。 思路&#xff1a; 我们只需要去枚举对于A来说每一层和他一样高&#xff08;人的身高和楼…

DNS协议详解

DNS协议详解 DNS协议介绍DNS解析过程DNS查询的方式递归查询迭代查询区别 DNS协议介绍 DNS 协议是一个应用层协议&#xff0c;它建立在 UDP 或 TCP 协议之上&#xff0c;默认使用 53 号端口。该协议的功能就是将人类可读的域名 (如&#xff0c;www.qq.com) 转换为机器可读的 IP…

uniapp 微信小程序 页面+组件的生命周期顺序

uniapp 微信小程序 页面组件的生命周期顺序 首页页面父组件子组件完整顺序参考资料 首页 首页只提供了一个跳转按钮。 <template><view><navigator url"/pages/myPage/myPage?namejerry" hover-class"navigator-hover"><button ty…

数据结构---顺序栈、链栈

特点 typedef struct Stack { int* base; //栈底 int* top;//栈顶 int stacksize //栈的容量; }SqStack; typedef struct StackNode { int data;//数据域 struct StackNode* next; //指针域 }StackNode,*LinkStack; 顺序栈 #define MaxSize 100 typedef struct Stack { int*…

PyTorch quantization observer

文章目录 PyTorch quantization observerbasic classstandard observersubstandard observer PyTorch quantization observer basic class nameinheritdescribeObserverBaseABC, nn.ModuleBase observer ModuleUniformQuantizationObserverBaseObserverBase standard observ…

智慧工厂4G+蓝牙+UWB+RTK人员定位系统解决方案

人员定位在智慧工厂的应用正逐渐受到重视&#xff0c;通过使用现代化的技术和智能终端设备&#xff0c;工厂管理者能够实时定位和跟踪员工的位置&#xff0c;方便进行人员调度管理和监督人员的工作情况&#xff1b;人员遇到紧急情况&#xff0c;可通过定位设备一键报警求救&…

vue 快速自定义分页el-pagination

vue 快速自定义分页el-pagination template <div style"text-align: center"><el-paginationbackground:current-page"pageObj.currentPage":page-size"pageObj.page":page-sizes"pageObj.pageSize"layout"total,prev,…

安全文件传输:如何降低数据丢失的风险

在当今数字化时代&#xff0c;文件传输是必不可少的一项工作。但是&#xff0c;数据丢失一直是一个令人头疼的问题。本文将探讨一些减少数据丢失风险的方法&#xff0c;包括加密、备份和使用可信的传输协议等。采取这些措施将有助于保护数据免受意外丢失的危险。 一、加密保护数…

24考研数据结构-栈

目录 第三章 栈和队列3.1栈&#xff08;stack&#xff09;3.1.1栈的基本概念栈的基本概念知识回顾 3.1.2 栈的顺序存储上溢与下溢栈的顺序存储知识回顾 3.1.3栈的链式存储链栈的基本操作 第三章 栈和队列 3.1栈&#xff08;stack&#xff09; 3.1.1栈的基本概念 栈的定义 栈…

通过ETL自动化同步飞书数据到本地数仓

一、飞书数据同步到数据库需求 使用飞书的企业都有将飞书的数据自动同步到本地数据库、数仓以及其他业务系统表的需求&#xff0c;主要是为了实现飞书的数据与业务系统进行流程拉通或数据分析时使用&#xff0c;以下是一些具体的同步场景示例&#xff1a; 组织架构同步&#…