当前位置: 首页 > news >正文

【手把手带你学JavaSE】第七篇:面向对象编程—包继承组合多态

❤️❤️个人主页:摸鱼王胖嘟嘟
🌟🌟作品专栏:【手把手带你学JavaSE系列】
📑给大家推荐一款非常火的面试、刷题、学习神器
👉牛客网
👉点击注册一起刷题、学习、讨论收获大厂offer吧!
在这里插入图片描述

目录

  • 前言
  • 一、包
    • 1.1 什么是包?
    • 1.2 怎么导入包中的类?
      • 1.2.1 导入方法一
      • 1.2.2 导入方法二
      • 1.2.3 导入方法三
    • 1.3 静态导入
    • 1.4 自定义包
      • 1.4.1 基本使用规则:
      • 1.4.2 IDEA中创键自定义包
    • 1.5 不同包中的访问权限控制
    • 1.6 常见的包
  • 二、面向对象三大特征—继承
    • 2.1 什么是继承?
    • 2.2 继承的语法
    • 2.3 父类成员的访问
      • 2.3.1 子类中访问父类的成员变量
      • 2.3.2 子类中访问父类的成员方法
    • 2.4 super关键字
    • 2.5 protected关键字
    • 2.6 final关键字
    • 2.7 继承与组合
  • 三、面向对象三大特征—多态
    • 3.1什么是多态?
    • 3.2 什么是重写?
    • 3.3 向上转型和向下转型
      • 3.3.1 向上转型
      • 3.3.2 向下转型
    • 3.4 多态实现条件
    • 3.5 多态的优缺点
      • 3.5.1 优势
      • 3.5.2 缺陷

前言

一、包

1.1 什么是包?

在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。 有点类似于目录。比如:为了更好的管理电脑中的图片,一种好的方式就是将相同属性的图片放在相同文件下,也可以对某个文件夹下的图片进行更详细的分类 。

在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。

1.2 怎么导入包中的类?

1.2.1 导入方法一

Java中提供的好多线程的类供我们使用
例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类.

public class Test1 {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

1.2.2 导入方法二

但是上面写法比较麻烦一些, 可以使用 import语句导入包

import java.util.Date;
public class Test1 {
    public static void main(String[] args) {
        Date date = new Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

1.2.3 导入方法三

如果需要使用 java.util 中的其他类, 可以使用 import java.util.* ,这里可以导入java.util这个包中的所有类,但要注意不是一下子将所有类都导进来,在代码中用到谁就会导入谁。

import java.util.*;
public class Test1 {
    public static void main(String[] args) {
        Date date = new Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

但是更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.

import java.util.*;
import java.sql.*;
public class Test1 {
    public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
        Date date = new Date();
        System.out.println(date.getTime());
    }
}


// 编译出错
//Error:(5, 9) java: 对Date的引用不明确
//java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配

在这种情况下需要使用完整的类名

import java.util.*;
import java.sql.*;
public class Test1 {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        System.out.println(date.getTime());
    }
}

注意事项:
import 和 C++ 的 #include 差别很大. C++ 必须 #include 来引入其他文件内容, 但是 Java 不需要. import 只是为了写代码的时候更方便. import 更类似于 C++ 的 namespace 和 using

知识点:
import和package的区别

1.package:“包”,,指:类所在的包

2.import:“引入”,指:引入类中需要的类

3.如果我们要用到一些Java类库里面的代码我们都需要通过import导入

1.3 静态导入

使用 import static 可以导入包中的静态的方法和字段.

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
   }
}

这样System.out.println(“hello”);就可以写成out.println(“hello”);

import static java.lang.Math.*;
public class TestDemo {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;
        // 静态导入的方式写起来更方便一些. 
        // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
   }
}

再写代码当中Math.就可以去掉。

1.4 自定义包

1.4.1 基本使用规则:

在文件的最上方加上一个 package 语句指定该代码在哪个包中.

包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.xuexiao.demo1 ).

包名要和代码路径相匹配. 例如创建 com.xuexiao.demo1 的包, 那么会存在一个对应的路径com/xuexiao/demo1 来存 储代码.

如果一个类没有 package 语句, 则该类被放到一个默认包中.

1.4.2 IDEA中创键自定义包

  1. 在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包
    在这里插入图片描述
  2. 在弹出的对话框中输入包名, 例如 com.xuexi.demo1 ,点回车

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

  1. 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可
    在这里插入图片描述
  2. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了

在这里插入图片描述

  1. 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句

在这里插入图片描述

1.5 不同包中的访问权限控制

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.

如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.

举例:
下面的代码给了一个示例. Demo1 和 Demo2 是同一个包中, Test 是其他包中.
Demo1.java

package com.bili.demo;
public class Demo1 {
    int value = 0;
}

Demo2.java

package com.bili.demo; 
public class Demo2 { 
 public static void Main(String[] args) { 
 Demo1 demo = new Demo1(); 
 System.out.println(demo.value); 
 } 
} 
// 执行结果, 能够访问到 value 变量
10 

Test.java

import com.bili.demo.Demo1; 
public class Test { 
 public static void main(String[] args) { 
 Demo1 demo = new Demo1(); 
 System.out.println(demo.value); 
 } 
} 
// 编译出错
Error:(6, 32) java: value在com.bili.demo.Demo1中不是公共的; 无法从外部程序包中对其进行访问

1.6 常见的包

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包;(集合类等)
  6. java.io:I/O编程开发包。

二、面向对象三大特征—继承

三大特征之一的封装咱们这里就不讲了,想看的可以去面向对象三大特征—封装查看!

2.1 什么是继承?

**继承(inheritance)机制:**是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类(子类)。

继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用

在这里插入图片描述
上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类/超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。

2.2 继承的语法

基本语法:

class 子类 extends 父类 {
}

此时将 1 中的设计思想使用代码实现:

// Animal.java
public class Animal{
    String name;
    int age;
    public void eat(){
        System.out.println(name + "正在吃饭");
    }
    public void sleep(){
        System.out.println(name + "正在睡觉");
    }
}

// Dog.java
public class Dog extends Animal{
    void bark(){
        System.out.println(name + "汪汪汪~~~");
    }
}

// Cat.Java
public class Cat extends Animal{
    void mew(){
        System.out.println(name + "喵喵喵~~~");
    }
}

// TestExtend.java
public class TestExtend {
    public static void main(String[] args) {
        Dog dog = new Dog();
        // dog类中并没有定义任何成员变量,
        //name和age属性是从父类Animal中继承下来的
        System.out.println(dog.name);
        System.out.println(dog.age);
        //dog访问的eat()和sleep()方法也是从Animal中继承下来的
        dog.eat();
        dog.sleep();
        dog.bark();
    }
}

注意:
1.子类会将父类中的成员变量或者成员方法继承到子类中了
2.子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

2.3 父类成员的访问

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

  1. 子类和父类不存在同名成员变量
public class Base {
    int a;
    int b;
}

public class Derived extends Base{
    int c;
    public void method(){
        a = 10; // 访问从父类中继承下来的a
        b = 20; // 访问从父类中继承下来的b
        c = 30; // 访问子类自己的c
    }
}

  1. 子类和父类成员变量同名
public class Base {
    int a;
    int b;
    int c;
}

public class Derived extends Base{
    int a; // 与父类中成员a同名,且类型相同
    char b; // 与父类中成员b同名,但类型不同
    public void method(){
        a = 100; // 访问子类自己新增的a
        b = 101; // 访问子类自己新增的b
        c = 102; // 子类没有c,访问从父类继承下来的c
        // d = 103; // 编译失败,因为父类和子类都没有定义成员变量d
    }
}

在子类方法中 或者 通过子类对象访问成员时:
1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。

成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

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

  1. 父类和子类的成员方法名字不同
public class Base {
    public void methodA(){
        System.out.println("Base中的methodA()");
    }
}

public class Derived extends Base{
    public void methodB(){
        System.out.println("Derived中的methodB()方法");
    }
    public void methodC(){
        methodB(); // 访问子类自己的methodB()
        methodA(); // 访问父类继承的methodA()
        // methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()
    }
}

  1. 父类和子类的成员方法名字相同
public class Base {
    int a;
    int b;
    public void methodA(){
        System.out.println("Base中的methodA()");
    }
    public void methodB(){
        System.out.println("Base中的methodB()");
    }
}

public class Derived extends Base{
    public void methodA(int a) {
        System.out.println("Derived中的method(int)方法");
    }
    public void methodB(){
        System.out.println("Derived中的methodB()方法");
    }
    public void methodC(){
        methodA(); // 没有传参,访问父类中的methodA()
        methodA(20); // 传递int参数,访问子类中的methodA(int)
        methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
    }
}

注意:

  1. 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问;否则在父类中找,找到则访问,如果父类中也没有则编译报错
  2. 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问;如果没有则报错。
  3. 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表、返回值都相同,则遵循就近原则,直接访问子类中的方法,不会访问父类中的方法

2.4 super关键字

子类构造的同时,要先帮助父类来进行构造
在这里插入图片描述
当为父类创建一个构造方法的时候,我们的子类就报错了!
在这里插入图片描述
像这样我们就不会报错了!

super三种用法:不能出现在静态方法当中,因为super相当于父类对象的引用
1、super():调用父类的构造方法
2、super.function():调用父类的普通方法
3、super.data:调用父类的成员属性

2.5 protected关键字

在这里插入图片描述
注意:如果和子类在不同包中,父类中的成员被protected修饰,那么子类的成员方法中要想访问父类中的成员必须通过super关键字来访问;父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

// extend01包中
public class B {
    private int a;
    protected int b;
    public int c;
    int d;
} 

// extend01包中
// 同一个包中的子类
public class D extends B{
    public void method(){
     // super.a = 10; // 编译报错,父类private成员在相同包子类中不可见
        super.b = 20; // 父类中protected成员在相同包子类中可以直接访问
        super.c = 30; // 父类中public成员在相同包子类中可以直接访问
        super.d = 40; // 父类中默认访问权限修饰的成员在相同包子类中可以直接访问
    }
} 

// extend02包中
// 不同包中的子类
public class C extends B {
    public void method(){
      //super.a = 10; // 编译报错,父类中private成员在不同包子类中不可见
        super.b = 20; // 父类中protected修饰的成员在不同包子类中可以直接访问
        super.c = 30; // 父类中public修饰的成员在不同包子类中可以直接访问
      //super.d = 40; // 父类中默认访问权限修饰的成员在不同包子类中不能直接访问
    }
} 

// extend02包中
// 不同包中的类
public class TestC {
    public static void main(String[] args) {
        C c = new C();
        c.method();
// System.out.println(c.a); // 编译报错,父类中private成员在不同包其他类中不可见
// System.out.println(c.b); // 父类中protected成员在不同包其他类中不能直接访问
        System.out.println(c.c); // 父类中public成员在不同包其他类中可以直接访问
// System.out.println(c.d); // 父类中默认访问权限修饰的成员在不同包其他类中不能直接访问
    }
}

2.6 final关键字

曾经我们学习过 fifinal 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改).

fi nal i nt a = 10 ; 
a = 20 ; // 编译出错

final 关键字也能修饰类, 此时表示被修饰的类就不能被继承.

final public class Animal {
...
}

public class Bird extends Animal {
...
} 

// 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继

修饰方法:final修饰的方法叫做密封方法,不能被重写。

2.7 继承与组合

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

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a的关系,比如:汽车和其轮胎、发动机、方向盘、车载系统等的关系就应该是组合,因为汽车是有这些部件组成的。

// 轮胎类
class Tire{
// ...
} /
        / 发动机类
class Engine{
// ...
} /
        / 车载系统类
class VehicleSystem{
// ...
}
class Car{
    private Tire tire; // 可以复用轮胎中的属性和方法
    private Engine engine; // 可以复用发动机中的属性和方法
    private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
} /
        / 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}

三、面向对象三大特征—多态

3.1什么是多态?

俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态; 同一件事情,发生在不同对象身上,就会产生不同的结果。

3.2 什么是重写?

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

规则:

  1. 子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
  2. 被重写的方法返回值类型可以不同,但是必须是具有父子关系的
  3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected
  4. 父类被static、private、final修饰的方法,构造方法都不能被重写。
  5. 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写

重写和重载的区别
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现
在这里插入图片描述
重写的设计原则
对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。

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

3.3 向上转型和向下转型

3.3.1 向上转型

向上转型:一句话,父类引用,引用子类对象
在这里插入图片描述

class Animal{
    public String name;
    public int age;
 
    public void eat(){
        System.out.println("eat()");
    }
 
    public Animal(String name,int age){
        this.name = name;
        this.age = age;
    }
}
class Dag extends Animal {
    public Dag(String name,int age){
        super(name,age);
    }
 
 
}
class Bird extends Animal{
 
    public String wing;
 
    public void fly(){
        System.out.println(age+"fly");
 
    }
 
    public Bird(String name,int age,String wing){
        super(name,age);
        this.wing = wing;
    }
 
}
public class Test{
    public static void main(String[] args) {
        //Dag dag = new Dag("HAHAH",12);
        //Animal animal = dag;
        Animal animal = new Dag("HAHAH",12);
    }

什么情况下会发什么向上转型:
1、直接赋值
2、方法传参
3、方法返回

直接赋值的方式我们已经演示了. 另外两种方式和直接赋值没有本质区别

方法传参:
在这里插入图片描述
此时形参 animal 的类型是 Animal (基类), 实际上对应到 Dag (父类) 的实例

方法返回
在这里插入图片描述
向上转型的优点:让代码实现更简单灵活。
向上转型的缺陷:不能调用到子类特有的方法。

3.3.2 向下转型

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

public class TestAnimal {
    public static void main(String[] args) {
        Cat cat = new Cat("haha",2);
        Dog dog = new Dog("hehe", 1);
        
        // 向上转型
        Animal animal = cat;
        animal.eat();
        animal = dog;
        animal.eat();
        
        // 编译失败,编译时编译器将animal当成Animal对象处理
        // 而Animal类中没有bark方法,因此编译失败
        // animal.bark();
        
        // 向上转型
        // 程序可以通过编程,但运行时抛出异常---因为:animal实际指向的是狗
        // 现在要强制还原为猫,无法正常还原,运行时抛出:ClstException
        cat = (Cat)animal;
        cat.mew();
        
        // animal本来指向的就是狗,因此将animal还原为狗也是安全的
        dog = (Dog)animal;
        dog.bark();
    }
}

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。

instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

public class TestAnimal {
    public static void main(String[] args) {
        Cat cat = new Cat("haha",2);
        Dog dog = new Dog("hehe", 1);
        
        // 向上转型
        Animal animal = cat;
        animal.eat();
        animal = dog;
        animal.eat(); 
        
        if(animal instanceof Cat){
            cat = (Cat)animal;
            cat.mew();
        } 
        if(animal instanceof Dog){
            dog = (Dog)animal;
            dog.bark();
        }
    }
}

3.4 多态实现条件

在java中要实现多态,必须要满足如下几个条件,缺一不可:

1.必须在继承体系下
2.子类必须要对父类中方法进行重写
3.通过父类的引用调用重写的方法

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

实现多态的实例:

public class Animal {
    String name;
    int age;
    public Animal(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println(name + "吃饭");
    }
}
public class Cat extends Animal{
    public Cat(String name, int age){
        super(name, age);
    } 
    @Override
    public void eat(){
        System.out.println(name+"吃鱼");
    }
}
public class Dog extends Animal {
    public Dog(String name, int age){
        super(name, age);
    } 
    @Override
    public void eat(){
        System.out.println(name+"吃骨头");
    }
}

///分割线//

public class TestAnimal {
// 编译器在编译代码时,并不知道要调用Dog 还是 Cat 中eat的方法
// 等程序运行起来后,形参a引用的具体对象确定后,才知道调用那个方法
// 注意:此处的形参类型必须时父类类型才可以
    public static void eat(Animal a){
        a.eat();
    }
    public static void main(String[] args) {
        Cat cat = new Cat("haha",2);
        Dog dog = new Dog("hehe", 1);
        eat(cat);
        eat(dog);
    }
} 

3.5 多态的优缺点

3.5.1 优势

  1. 能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
  2. 可扩展能力更强
  3. 类调用者对类的使用成本进一步降低

3.5.2 缺陷

  1. 代码的运行效率降低
  2. 属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性 。
  3. 构造方法没有多态性 。

相关文章:

  • 攻防世界WEB练习-fileinclude
  • web自动化测试--tpshop商城案例
  • 数据结构与算法分析--c语言描述(原书第二版)练习自答(第八章)
  • Selenium--定位页面上的元素
  • JTAG、SWD调试原理简析
  • cmake语法:option,add_definition,add_dependencies的基本作用
  • Nmap详细使用
  • CREO:CREO软件之工程图【注释】之尺寸、注解、表面粗糙度、符号、几何公差的简介及其使用方法(图文教程)之详细攻略
  • FastAPI 学习之路(三十)中间件
  • Springboot整合redis
  • Python对象序列化
  • Linux-Linux内核-进程调度
  • LabVIEW重入:允许同时调用同一子VI
  • 『网易实习』周记(五)
  • 【glib】vs2022 v163 debug win32: meson构建 glib-2.67.6
  • 2017-08-04 前端日报
  • Angular 响应式表单之下拉框
  • canvas绘制圆角头像
  • centos安装java运行环境jdk+tomcat
  • ES2017异步函数现已正式可用
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Java IO学习笔记一
  • Sass Day-01
  • spring boot下thymeleaf全局静态变量配置
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue2.0项目引入element-ui
  • vue脚手架vue-cli
  • 创建一种深思熟虑的文化
  • 汉诺塔算法
  • 基于web的全景—— Pannellum小试
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 盘点那些不知名却常用的 Git 操作
  • 配置 PM2 实现代码自动发布
  • 前端工程化(Gulp、Webpack)-webpack
  • 前端知识点整理(待续)
  • 区块链共识机制优缺点对比都是什么
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 微信公众号开发小记——5.python微信红包
  • 微信小程序填坑清单
  • 我是如何设计 Upload 上传组件的
  • 由插件封装引出的一丢丢思考
  • 与 ConTeXt MkIV 官方文档的接驳
  • 怎样选择前端框架
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • *上位机的定义
  • .mysql secret在哪_MySQL如何使用索引
  • .NET Core 版本不支持的问题