C# 接口《通俗解释》

2023-05-16

原文地址:https://www.cnblogs.com/hamburger/p/4681681.html

 

  • 接口的定义: 
    接口是指定一组函数成员,而不实现他们的引用类型。 
    接口使用interface 关键字进行定义,可由方法、属性、事件、索引器或这四种成员类型的任意组合构成。

  • 接口的特点: 
    1、接口类似于抽象基类,不能直接实例化接口;接口中的方法都是抽象方法,实现接口的任何非抽象类型都必须实现接口的所有成员: 
    2、当显式实现该接口的成员时,实现的成员不能通过类实例访问,只能通过接口实例访问。 
    3、当隐式实现该接口的成员时,实现的成员可以通过类实例访问,也可以通过接口实例访问,但是实现的成员必须是公有的。 
    4、接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型、不能包含静态成员。 
    5、接口成员是自动公开的,且不能包含任何访问修饰符。 
    6、接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。 
    7、当一个类既继承基类,又继承接口的时候,必须基类写在前面,基类和接口用逗号隔开,一个类只能有一个基类,可以继承许多接口

    /// <summary>
    /// 定义一个爬树接口
    /// </summary>
    interface IClimbTree
    {
        void ClimbTree();
    }

    /// <summary>
    /// 定义一个抓老鼠接口
    /// </summary>
    interface ICatchMice
    {
        void CatchMice();
    }

    /// <summary>
    /// 定义一个宠物类
    /// </summary>
    public class Pet
    {
        public void Eat()
        {
            Console.WriteLine("吃着真香");
        }
    }

    /// <summary>
    /// 狗狗类,继承于宠物类,又实现了爬树和抓老鼠接口
    /// </summary>
    public class Cat:Pet,IClimbTree,ICatchMice
    {

        public void ClimbTree()
        {
            Console.WriteLine("我会爬树");
        }

        public void CatchMice()
        {
            Console.WriteLine("我会抓老鼠");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //实例化一个猫咪对象
            Cat cat = new Cat();
            cat.Eat();
            cat.ClimbTree();
            cat.CatchMice();
            Console.ReadLine();
        }
    }

输出结果:这里写图片描述

  • 显示实现接口
        public void IClimbTree.ClimbTree()
        {
            Console.WriteLine("我会爬树");
        }

        public void ICatchMice.CatchMice()
        {
            Console.WriteLine("我会抓老鼠");
        }
  • 隐式实现接口
        public void ClimbTree()
        {
            Console.WriteLine("我会爬树");
        }
        public void CatchMice()
        {
            Console.WriteLine("我会抓老鼠");
        }
  • 一般情况,当类或者结构要实现的是单个接口,可以使用隐式实现。 
    如果类或者结构继承了多个接口且接口中具有相同名称成员时,就要用到显式实现,当显式实现方式存在时,隐式实现方式就失效了。

  • 接口和抽象类的区别 
    1、接口用于规范,抽象类用于共性。 
    2、接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。 
    3、抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。 
    4、抽象类可以提供某些方法的部分实现,接口不可以。 
    5、抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。 
    6、在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写。 
    7、接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。 
    8、接口不能包含字段、构造函数、析构函数、静态成员或常量。

 

 

思考一: C#中接口和抽象类的使用上的区别:              

  ---------------YYC

                1、抽象类不能被实例化,但能拥有自己的成员字段和非抽象的方法,但接口比抽象类更加抽象,其成员只能是
                    一般的方法、属性和索引函数而不能拥有自己的成员字段和构造函数。
                2、用abstract声明的抽象类中的方法必须有访问修饰符如public等关键字进行修饰,其次抽象类里面的方
                   法须用abstract声明为抽象方法或则用virtual声明为虚拟方法(非抽象方法除外,虚拟方法有简单执
                   行代码,派生类中可以选择不重载,抽象方法没有任何执行代码,派生类中必须重载)。在其派生类
                   中重载抽象方法或虚拟方法时时必须用override修饰。而在用interface声明的接口类中的接口方法第
                   一不允许是静态的,其次除了无执行代码外
                   不能加任何访问限制修饰符,且不能用virtual或abstract进行修饰。同时在直接支持其接口的类型中不能用
                   override修饰符来表示重载方法,且必须支持即实现该接口中的所有方法。但可以用new关键字来隐藏父接口中的方法。

                 3、接口、抽象类、非抽象类都可以继承接口

                 4、继承接口后对其接口方法的实现:

                                 实现可以分为“显示实现”和”隐式实现“

 interface Interface1

    {
        int GetInt();
        //派生类必须实现接口类里面的每一个方法
    }

class cl1 :Interface1
        { 
          public int GetInt()  //隐式实现
          {
              return 1;
          }
        }

 

 class cl2 : Interface1
        {
            public int GetInt()//隐式实现
            {
                return 2;
            }
            int Interface1.GetInt()//显示实现
            {
                return 4;
            }
        }

其中两者的区别是:隐式实现的方法既可以同接口对象调用,也可以通过派生类的实例来调用。

而对于显示实现的方法只可以通过接口对象来调用。而且显示实现时该方法前不能加任何的访问

修饰符,其实默认的为隐式的,所以派生类的对象不能调用该方法。

 

思考二:接口在C#中出现的意义。

 一、解决了多态和动态隐藏不能统一的问题。

a、动态隐藏:在没有接口机制的动态隐藏是通过new关键字来隐藏基类的方法,从而

实现了基类对象和派生类对象通过使用相同方法名分别调用不同的方法;而在有接口的机制中是通过对于接口中的接

口方法的隐式实现和显示实现同时共存的方法来实现接口对象和派生类对象通过使用相同方法名分别调用不同的方法。

For example://接口的动态隐藏

 

cl2 c2 = new cl2();

 Interface1 iter = c2;

 MessageBox.Show(c2.GetInt());//输出2  ------会调用隐式方法

 MessageBox.Show(iter.GetInt());//输出4  -------会调用显示方法

b、多态的实现:在没有接口的机制中,多态的实现是通过使用关键字abstract/virtual--override的重载来实现

的;而在接口机制中的多态直接通过显示实现多隐式实现都可以完成。

For example://接口的多态

 

cl1 c1 = new cl1();

cl2 c2 = new cl2();

 Interface1 iter = c1;

MessageBox.Show(iter.GetInt());//输出1

Interface1 iter = c2;

MessageBox.Show(iter.GetInt());//输出4  --------会调用显示方法,如果没有显示实现则会调用隐式实现方法。

                c:问题:关键问题就是在没有接口的机制中new机制和abstract/virtual--override不能同时出现,但是

在接口机制中通过同时显示实现和隐式实现方法共存,就可以很轻松的解决该问题了。在C#接口机制下的动态

隐藏和多态同时实现有至少三种模式:

For example:

 

/*模式一:*/

 

cl1 c1 = new cl1();

cl2 c2 = new cl2();

 Interface1 iter = c1;

MessageBox.Show(iter.GetInt());//输出1

Interface1 iter = c2;

MessageBox.Show(iter.GetInt());//输出4  --------会调用显示方法,如果没有显示实现则会调用隐式实现方法。

MessageBox.Show(c2.GetInt());//输出2

//输出2和4实现了1和4实现了多态,输出2和4实现动态隐藏

 

/*模式二:*/

从新写cl1类

 class cl1 :Interface1
        { 
          public virtual int GetInt()//隐式实现
          {
              return 1;
          }
          int Interface1.GetInt()//显示实现
          {
              return 3;
          }


        }


        class cc : cl1 

{
            public override int GetInt()
            {
                return 5;
            }
  }


        class cd : cl1
        {

            public override int GetInt()
            {
                return 6;
            }
        }

 

cl1 c1 = new cl1();

Interface1 iter = c1;

//动态隐藏

MessageBox.Show(iter.GetInt());//输出3  ---显示实现

MessageBox.Show(c1.GetInt());//输出1--------显示实现

cc cc1= new  cc();

cd cd1 =  new cd();

//多态

c1 = cc1;

MessageBox.Show(c1.GetInt());//输出5

c2= cd1;

MessageBox.Show(c1.GetInt());//输出6

 

所以运用接口就可以轻松地解决多态和动态隐藏的统一问题了。

 

      二、实现多继承问题

实现多继承也是接口在C#中很独特和很重要的功能之一,

 

现在接着上篇博客写,上次是写到了关于C#中接口出现的意义的第二点:实现多继承。

在C#语言中本身就有规定一个类只能有一个直接基类,也就是不允许出现多继承,这个主要

是基于两个方面原因的考虑: 

(上一部分的连接是http://blog.csdn.net/yyc1023/article/details/17270951)

--------------------YYC

一、多继承很容易出现“二义性”,也就是在两个或以上的基类中出现了相同名字的方法时,

在其派生类中通过base关键字调用父类中该方法时就会引发歧义。

二、多继承会严重的影响程序的性能,例如:首先:在存储空间方面派生类的对象所占的

空间将会是其所以的基类对象的内存空间之和;其次:派生类的对象在创建时会依次调用其所

有的基类的构造函数,所以其效率肯定会有所下降,特别是当一个类有过多的基类时这个问题

将会变得很明显的。

 

但是多继承又是面向对象的程序设计中非常重要的一个特性,所以C#在考虑这个问题时就提出

了基于接口的多继承,也就是说在C#语言中允许一个类或接口同时继承多个接口,在声明时分

别用逗号隔开即可。

For example:

  public interface IA 
        {
            int GetInt();
        }


        public interface IB
        {
            int GetInt();
        }


        class CA : IA, IB
        {


            int IA.GetInt()
            {
                return 1;
            }


            int IB.GetInt()
            {
                return 2;
            }


        }

由上可以看出用基于接口实现的多继承的优点是:首先:这个更本不会引起程序性能的问题,因为

接口中是不能出现成员字段和实体方法和构造函数的。其次:关于“二义性”的问题在接口的多继承中

只要多显示实现不同接口的相同名字的接口方法即可很容易消除了二义性了,因为在通过不同接口对

象在调用该方法时都只会调用自己的显示实现的方法。

 

 

接口

为什么要用接口?好处在哪里?

如果你的工作是一个修水管的,一天客户找上你让你帮装水管,但是有个要求,就是客户喜欢管子是三角形的。

你立马买了三角形的水管回来,在墙上弄个三角形的口子,客户付了钱,你很开心今天有了收入,如下图,很好:

但是好景不长,客户过了一个星期又来找,因为他觉得三角形不好看,要让你换成正方形的水管,你不得不换,因为顾客就是上帝。好吧,继续在墙上弄个正方形的口子,然后又换成正方形的管子来接上。好了,如下图:(但是可能觉得为什么一开始不说要正方形的?因为需求总在变化。。。)

你累得满头大汗,但是还是完成了。可惜不久,客户又来找你,因为他想换成椭圆形的管子了。虽然你很无奈,但是你还是不得不花了几个小时完成。如下图:

安装完成,这时你可能在考虑,为什么换不同形状的水管,我都要大动干戈一番呢?于是你想到一个好方法,那就是墙上设计一个固定的水管并且是圆形的,当客户喜欢什么形状的水管,那么我只需要把客户喜欢的水管的一头做成圆形的,这样,以后都不需要去动墙上的水管了。这是一个好办法。就先在墙上弄个圆形的口,这个口就叫做接口。如下图:

如你所见,墙上有个圆形的口,但是按照原本的:

三角形水管两端是三角形
正方形水管两端是正方形
椭圆形水管两端是椭圆形

那是肯定接不上的,因为三角形、正方形、椭圆形的口怎么和墙壁上圆形的口对接呢?

所以先要实现接口,把:

三角形水管一端做成圆形
正方形水管一端做成圆形
椭圆形水管一端做成圆形

如图所以,圆形接口做出来了,具体实现是客户去安装,接口本身并不会安装其他形状的水管,换句话说就是接口没有具体实现,只是告诉你,你的水管要接入,必须有一端是圆形的(接口的约束),因为我只留这个圆形的接口,你要装别的形状的管子,先把一个弄成圆形的就好了(子类去实现接口的方法),不管什么形状,都要一个必须做成圆形才能对接得上,它必须要你按照我的规范来做。这就是为什么新手会觉得接口什么都不做,只定义接口,没有任何实现,那不是多此一举吗?因为它的实现是子类去完成。这样只要客户喜欢什么形状的水管,只要实现了我的接口(圆形),都能对接得上,而且改变起来也很方便,只要把水管扭上去就行了,不用在去给墙壁挖洞了

下面我们在代码里体现接口的作用,以下例子的场景不讨论是否合理,由于以下代码是在txt编写,不保证运行无误。

需求:公司有两个人分别写了2个动物类,让你写一个类来输出它们各自喜欢的食物。

复制代码

//A写的Dog类,里面有个likeFood方法,如下:
class Dog 
{

    public void likeFood()
    {
        Console.WriteLine("我是小狗,我喜欢吃肉");
    }
    
}
//B写的Cat类,里面有个likeFood方法,如下:
class Cat 
{

    public void likeFood()
    {
        Console.WriteLine("我是小猫,我喜欢吃鱼");
    }
    
}

复制代码

你写的Zoo类如下:

复制代码

//动物园类
class Zoo {

    public void show(Dog dog){
        dog.likeFood();
    }

    public void show(Cat cat){
        cat.likeFood();
    }

}

复制代码

在输出的时候使用如下:

复制代码

public static void Main(string[] args) 
{
    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"

}

复制代码

这一切工作良好,但好景不长,公司又需要给动物园增加一个猴子,让C去写这个Monkey类,并能输出它喜欢的食物。

复制代码

class Dog 
{

    public void likeFood()
    {
        Console.WriteLine("我是小狗,我喜欢吃肉");
    }
    
}
//B写的Cat类,里面有个likeFood方法,如下:
class Cat 
{

    public void likeFood()
    {
        Console.WriteLine("我是小猫,我喜欢吃鱼");
    }
    
}
//C写的Monkey类,里面有个likeFood方法,如下:
class Monkey 
{

    public void likeFood()
    {
        Console.WriteLine("我是猴子,我喜欢吃桃子");
    }
    
}

复制代码

于是你的Zoo类就变成了这样,仅仅多了一个重载方法:

复制代码

class Zoo 
{

    public void show(Dog dog)
    {
        dog.likeFood();
    }

    public void show(Cat cat)
    {
        cat.likeFood();
    }

    public void show(Monkey money)
    {
        money.likeFood();
    }
}

复制代码

复制代码

public static void Main(string[] args) 
{

    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"
    zoo.show(new Monkey()); //"我是猴子,我喜欢吃桃子"

}

复制代码

输出结果也良好,你不禁暗暗得意,一个变化而已,我只需要再Zoo类里增加一个重载方法就好了。
但你仔细一想:“如果后面还有更多动物要输出它们喜欢的食物,我的Zoo类都要修改,这对我来说不是一件好事。”
然后你再仔细观察Zoo类,发现不变的是show方法,变化的是show方法是参数。因为每个动物都不一样,所以参数也就不一样。所以原来就需要重载多个方法。
如果有一个类,能接收所有动物,那不就解决了?没错,于是你想到了定义一个父类叫Animal,里面有个likeFood方法,让所有动物类去继承Animal。
最后你的Zoo类和Animal类代码如下:

复制代码

class Zoo 
{

    public void show(Animal animal)
    {
        animal.likeFood();
    }

}

class Animal 
{

    public void likeFood()
    {
        Console.WriteLine("我是Animal类");
    }

}

复制代码

你告诉原来的A和B两人,让它们写的动物类都去继承Animal,并且里面有个输出动物喜欢食物的方法。
A、B、C写的类修改后如下:

复制代码

class Dog : Animal 
{

    public void likeFood()
    {
        Console.WriteLine("我是小狗,我喜欢吃肉");
    }
    
}

class Cat : Animal 
{

    public void likeFood()
    {
        Console.WriteLine("我是小猫,我喜欢吃鱼");
    }
    
}

class Monkey : Animal 
{

    public void likeFood()
    {
        Console.WriteLine("我是猴子,我喜欢吃桃子");
    }
    
}

复制代码

Zoo也需要修改,最后代码如下:

复制代码

class Zoo 
{

    public void show(Animal animal)
    {
        animal.likeFood();
    }

}

public static void Main(string[] args) 
{

    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Monkey()); //"我是猴子,我喜欢吃桃子"

}

复制代码

 

运行也一切良好,不管你以后还有什么类,只要让需要添加的动物类,继承Animal,并有个likeFood方法,那么你无需修改Zoo,只需要再main方法里传入动物类的实例就能正常工作。
你大赞你聪明绝顶,这样一来,你的Zoo根本不需要改变了。
有一天,公司新来一个人,暂时叫D吧,公司让D写个兔子类,你告诉D,你写的Rabbit类必须继承Animal,并且有一个它喜欢的食物的方法,。
D写的兔子类如下:

复制代码

class Rabbit : Animal 
{

    public void favoriteFood()
    {
        Console.WriteLine("我是兔子,我喜欢吃萝卜");
    }
    
}

复制代码

复制代码

public static void Main(string[] args) 
{

    Zoo zoo = new Zoo();
    zoo.show(new Dog()); //"我是小狗,我喜欢吃肉"
    zoo.show(new Cat()); //"我是小猫,我喜欢吃鱼"
    zoo.show(new Monkey()); //"我是猴子,我喜欢吃桃子"
    zoo.show(new Rabbit()); //"我是Animal类"

}

复制代码

Raabit并没有输出预想的结果,你不得不花了点时间去排查原因,最后你发现这不是什么大问题,因为新来的D虽然写了Rabbit类,但是他并不知道你们之前约定的动物喜欢的食物命名为:likeFood()
D写的Rabbit类,里面的方法叫:favoriteFood()
虽然最后D修改他的Rabbit类的方法为likeFood(),但你还是对这个问题做了一番思考,为什么会导致这个问题?
那是因为没有一种约束,使得子类继承父类的时候必须实现父类的方法。有没有一个类,能让它的子类必须实现它定义的方法?有,那就是接口。
于是你修改Animal为接口,代码如下:

interface Animal {

    public void likeFood();
    
}

由于Animal接口有个likeFood()方法,那么Rabbit子类去实现Animal接口必须实现likeFood(),否则程序不能通过。

代码正常工作,因为Animal是接口,里面有个likeFood()方法,以后再添加各种动物进来,只需要实现Animal接口,并且也不会出现有的人会因为子类的方法命名问题而导致出错了。
这时你再想,虽然用继承一个普通父类也可以满足要求,但是一个普通父类根本没有约束力
而用了接口就不一样了,子类必须实现父类的所有方法,因为Zoo类里调用的是likeFood(),由于子类必须实现父类,那么所有子类都会有likeFood(),你根本不用担心子类有没有这个方法。
所以接口能在多人协作下,定义一系列方法,让子类必须存在接口定义的类,防止在另外的类里调用一个人写的接口的子类时,找不到方法的问题。

 

开放闭关原则:

对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

 

这两句话是概念性的东西。通俗的意思就是:

对于上面的图片来说,墙上的接口做好了,不能去改变了,但是可以扩展,你要什么形状的水管就去实现它的接口。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 接口《通俗解释》 的相关文章

  • django中vue的使用

    转载 xff1a https blog csdn net qq 21389693 article details 105734696 后端使用vue的目的 后端使用vue的目的就是把ajax里面的数据绑定到前端 xff0c 实现动静分离 V
  • centos7更新yum源

    1 centos7安装后 xff0c 默认yum源配置文件位置 xff1a vi etc yum repos d CentOS Media repo 2 下载新的国内yum源 centos自带的是国外yum源 xff0c 下载速度相当慢 换
  • 临时出差宁波随笔

    因公司吉利项目收尾工作 xff0c 需到客户现场施工 主要负责软件项目的质量查验 xff0c 及相关问题修复 一千多公里的路程 xff0c 坐高铁7小时左右 xff0c 真是体验了中国速度 一路由西北而向东南直下 xff0c 抵达舟山群岛附
  • GitHub Copilot

    介绍 GitHub Copilot 是人工智能编程助手 xff0c 它可以帮助你编写程序 在你用visual studio或visual studio code等软件设计工具进行编程时 xff0c 它可以直接给你整行或整个方法的代码提示 x
  • 微信小程序头像昵称填写功能

    自 2022 年 10 月 25 日 24 时后 xff08 以下统称 生效期 xff09 xff0c 用户头像昵称获取规则将进行如下调整 xff1a 自生效期起 xff0c 小程序 wx getUserProfile 接口将被收回 xff
  • mysql 5.7设置数据库大小写敏感

    1 此处讲的是windows环境下的mysql配置 xff0c 小编用的是win10系统 xff1b 2 安装完mysql后 xff0c 数据库默认是大小写不敏感的 xff1b 3 修改my ini文件 xff1a C ProgramDat
  • eclipse 护眼色设置

    1 调整eclipse editor区域背景色 背景颜色向你推荐 xff1a 色调 xff1a 85 饱和度 xff1a 1 2 3 亮度 xff1a 2 0 5 文档都不再是刺眼的白底黑字 xff0c 而是非常柔和的豆沙绿色 xff0c
  • Js apply方法详解,及其apply()方法的妙用

    Js apply方法详解 我在一开始看到javascript的函数apply和call时 非常的模糊 看也看不懂 最近在网上看到一些文章对apply方法和call的一些示例 总算是看的有点眉目了 在这里我做如下笔记 希望和大家分享 如有什么
  • 如何安装双系统之ubuntu安装

    如何安装双系统之ubuntu安装 1 首先在Windows下对磁盘分出一块空闲分区大概100G左右 2 然后下载Ubuntu16 04镜像 xff0c 制作启动盘 3 重启电脑 xff0c 按住对应的键 xff08 不同电脑型号可能不同 x
  • 场景分类综述——Remote Sensing Image Scene Classification Meets Deep Learning

    一 场景分类面临的挑战 场景分类的挑战包括 xff1a 1 类内多样性大 xff0c 2 类间相似性高 也称为类间可分性低 xff0c 3 对象 场景尺度的差异大 就类内的多样性而言 xff0c 挑战主要来自于在同一个语义类中出现的地物的巨
  • 配置服务器的磁盘阵列并正确分区

    磁盘阵列 xff0c 即独立磁盘冗余阵列RAID xff08 Redundant Array of Independent Disks xff09 xff0c 其实就是一个将多块独立磁盘结合在一起 xff0c 从而提高数据的可靠性和I O性
  • 软件项目组织架构安排

    这个主题涉及到三个方面 xff0c 项目计划管理 组织管理和技术管理范畴 项目计划管理是项目管理中的一个大篇章 xff0c 包括时间计划 成本计划 费用计划等在内的各类计划管理 xff0c 不是本文章所谈的范围 xff0c 只是本文主题涉及
  • SpringBoot2.x学习(二):为属性注入配置文件中的值:@ConfigurationProperties注解的使用

    文章目录 一 64 ConfigurationProperties 简单介绍二 64 ConfigurationProperties 使用示范1 创建两个 javaBean2 在 SpringBoot 全局配置文件写入需要注入的值2 1 a
  • SpringBoot 2.x学习(三):为属性注入配置文件中的值:@Value 注解的使用

    文章目录 一 64 Value 注解的作用二 使用 64 Value 为普通成员变量注入值1 字面量 xff08 1 xff09 语法 xff08 2 xff09 举例 2 Spring 表达式 xff08 SpEL xff09 xff08
  • 数据结构与算法学习(一):线性表之数组的插入与删除(Java 实现)

    文章目录 一 数组介绍1 线性表2 连续的内存空间和类型相同的数据 二 利用数组实现插入操作及相应的时间复杂度分析1 数组原本有顺序 xff0c 插入后需要继续保持数组有序 xff08 1 xff09 思路分析 xff08 2 xff09

随机推荐

  • 抽象类与接口

    抽象类与接口 接口与抽象类 一 抽象类 说起抽象类 xff0c 我们先说一下如何定义一个抽象方法 span class token keyword abstract span span class token keyword class s
  • SpringBoot 项目集成 mybatis-generator

    SpringBoot 项目集成 mybatis generator mybatis 官方提供了一个插件 xff1a myabtis generator xff0c 可以根据数据库中的表生成对应的实体类和针对单表的一些操作方法 xff0c 可
  • InnoDB 和 MyISAM 的区别

    这里写自定义目录标题 MyISAMINNODB事务支持不支持支持数据行锁定不支持 xff08 表锁 xff09 支持 xff08 行锁 xff09 外键约束不支持支持全文索引支持不支持表空间的大小较小较大 xff0c 约为 2 倍 MyIS
  • xshell上传、下载文件

    安装 lrzsz yum y span class token function install span lrzsz 上传资源到服务器命令 rz 回车后 xff0c 会出现一个弹框 xff0c 选择上传的文件即可 从服务器下载资源命令 s
  • 浅谈vue+webpack项目调试方法

    题外话 xff1a 这几个月用vue写了三个项目了 xff0c 从绊手绊脚开始慢慢熟悉 xff0c 婶婶的感到语言这东西还是得有点框框架架 xff0c 太自由了容易乱搞 xff0c 特别人多的时候 从webpack开始 直接进入正题 有人觉
  • CentOS7下vlan网卡配置

    操作系统 xff1a CentOS 7 x86 64 Everything 1804 开源虚拟软件 xff1a Oracle VM VirtualBox 因为使用VirtualBox默认配置所以网卡设备名是enp0s3 root 64 lo
  • 12、基本数据链路层协议(数据链路层)

    1 基本数据链路层协议 引言 在考察协议之前 xff0c 先明确一下有关底层通信模型的基本假设是有必要的 首先我们假设物理层 数据链路层和网络层都是独立的进程 xff0c 它们通过来回传递信息进行通信 如图所示 xff0c 物理层进程和某些
  • Java 中的上转型和下转型

    在我们的日常中 xff0c 上转型和下转型都使用的比较少 xff0c 所以当别人问起来什么是上转型 xff0c 什么是下转型 xff0c 自己往往一片模糊 xff0c 或者不能将他们进行明显的区分 在这里 xff0c 我将以我个人理解来论述
  • MySQL 中 Join 的基本实现原理

    http isky000 com database mysql join buffer nested loop implement DataBase Dec 3rd 2008 作者 xff1a Sky Jian 可以任意转载 但转载时务必以
  • mysql 常用命令

    1 mysqldump 可以把现有数据库中的表结构以及数据导入到一个文本文件中 mysqldump u root socket 34 socketname 34 p tpch no data gt tpch sql 如果不加上 no dat
  • 完全二叉树学习

    定义 xff1a 假设高度为h xff0c 那么前h 1层都是满的 xff0c 最后一层 xff0c 从左向右 xff0c 连续集中在最左边 xff1b k层的完全二叉树总节点个数最小为2 k 1 xff0c 最大节点个数为2 k 1 可以
  • thrift例程编译报错原因和解决方法总结

    thrift里自带的turoral xff0c 使用make编译时经常会报错 xff0c 总结如下 xff1a 1 如果出现如下错误 xff1a error uint8 t does not name a type error uint32
  • C++11带来的move语义

    C 43 43 11带来了move语义 xff0c 可以有效的提高STL的效率 xff0c 这篇文章写的非常好 xff0c 可以参考 xff0c 这里对原文进行翻译 xff0c 加入我自己的理解 原文 xff1a http www cpro
  • C++11带来的lambda表达式

    C 43 43 11带来了lambda表达式 xff0c 可以简化程序的编写 xff0c 使代码更加清晰 现在按照步骤来介绍lambda表达式 xff1a 1 函数对象 又叫仿函数 xff0c 如果一个类或者结构体重载了operator 操
  • caffe中几个基本概念

    caffe中几个基本概念 1 caffe中的blob结构是用来进行数据存储 交换和处理网络中正向反向迭代时的数据和导数信息的数据结构 blob是caffe的标准数组结构 他提供了一个统一的内存接口 其将内部的cpu gpu数据之间的传输与存
  • 摄像头引脚定义

    摄像头引脚定义 1 NC NO CONNECT 2 AGND Power Analog ground 3 SIO D I O SCCB serial interface data I O 4 AVDD Power Analog power
  • Android7.0 JACK编译器不支持多用户同时编译的问题的解决

    xfeff xfeff Android7 0 xff08 也就是Android N xff09 上默认使用JACK编译器而不再使用openjdk了 xff0c 但发现JACK不是很好用 xff0c 比如最大的一个问题就是 xff0c 同一台
  • 【树莓派】死机自动重启、掉线自动重连

    目录 WIFI掉线自动重连 首先查看你的板子硬件型号 拿树莓派去做服务器就要配置下这两项 xff0c 保证随时能够VNC控制 WIFI掉线自动重连 http shumeipai nxez com 2017 01 25 raspberry p
  • open vswitch分析

    Open vSwitch 概述 Open vSwitch xff08 下面简称 OVS xff09 是一个高质量的 多层虚拟交换机 OVS 遵循开源 Apache2 0 许可 xff0c 通过可编程扩展 xff0c OVS 可以实现大规模网
  • C# 接口《通俗解释》

    原文地址 xff1a https www cnblogs com hamburger p 4681681 html 接口的定义 xff1a 接口是指定一组函数成员 xff0c 而不实现他们的引用类型 接口使用interface 关键字进行定