比较C Sharp和Java

2023-10-29

本文对比C#Java编程语言。 因为这两种语言都具有自动垃圾回收以及运行时编译执行的特点,并且他们的语法都是继承自C语言/C++,因此二者有个很多相似之处。

但由于C#也被描述为一个C++和Java的混合体,并添加了一些新特性,引入了一些变化,因此C#和Java自然也有很多不一样的地方。

这个条目描述了二者总体上的相似性,并例举了二者的不同点。


语言

对象处理

C#和Java都被设计成是一个使用动态调度的类似于C++语法的完全的面向对象语言。(C++又是源自于C)。但是,这两种语言都不是c或者c++的一个扩展集。C#和Java都使用垃圾回收的作为一种回收内存资源的手段,而不是直接的释放内存。C#和Java都包含线程同步机制也作为他们语法的一部分。

引用

C#允许指针的有限功能的使用,指针和运算指针在一个操作的环境中是存在潜在的不安全性的,因为他们的使用可以避开对象的一些严格访问规则。C#中使用指针的代码段或者方法的地址要用unsafe关键字进行标记,这样,这些代码的使用者就会知道这个代码相比其他的代码而言是不具有安全性的。编译器需要unsafe关键字将使用此代码的程序转换成是允许被编译的。一般来说,不安全代码的使用可能是为了非托管的API(应用程序编程接口)的更好互用,或者是为了(存在内在不安全性的)系统调用,也有可能是出于提高性能这方面的原因。而Java中不允许指针或者算术指针的使用。

数据类型

java和C#语言都有原始数据类型的概念,C#/.NET语言中支持的原始数据(所有的,除了string类型)都是值类型。但C#比java支持更多的原始数据类型,比如整型和十进制浮点数,尤其是java缺少无符号的BYTE类型,而C#的BYTE类型默认是无符号的。在两种语言中string其值都是不可改变的一个类,但是特殊的是C#为其提供了特殊的构造方法,同时C#还可以使用string的值就像值类型一样而不需要进行拆箱操作。 既允许自动装箱和拆箱,把它们从对象类型转换为原始数据。实际上,这使得原始类型成为对象类型的子类型。在C#中这也意味着,原始类型可以定义方法,如覆盖的对象的ToString()的方法。在Java中,单独的原始包装类提供这种功能。在Java中原始值不含隐式装箱和一个显示的类型转换都需要一个实例称为原始值的((Integer)42).toString()而不是C#中调用实例 42.ToString()。另一个不同之处在于,java使大量使用装箱类型(见下文),这样可以让一个隐式拆箱转换(在C #这需要一个类型转换)。由于这些隐性拆箱转换可能会抛出空指针例外,由于这些隐性拆箱转换可能会抛出空指针例外,现代集成开发环境和编译器可以配置为突出它们。 值类型 C#允许程序员用关键字struct创建用户自定义的值类型(value type)。 从程序员的角度来讲,它们可以被看做轻量级的类。

不同于一般类,而像标准基本类,这种值类型被分配在栈内存(stack)而不是堆内存(heap)。 结构体通常有一系列的限制,因为结构体没有空值的概念并且可以在数组中无需初始化而直接使用,这种类型也有必须用0来初始化内存空间的默认构造函数。 程序员只能定义另外的带有一个或多个参数的构造函数。

这也意味着结构体缺少一个虚方法表,正因为这样(还有固定的内存空间),它们不允许继承(但可以实现接口)。

数组

数组和集合类同样在语法中给出了重要意义,感谢基于迭代器的预声明循环。在C#里一个数组反映为一个数组类的对象,而在JAVA每个数组都是一个直接的对象集的子集(但是可以映射为一个以它真正的成员类为父类的一个数组),并且不实现任何的集合界面。C#拥有真正的多维数组,如同Java中可用到的数组的数组(在C#中通常称为锯齿数组)。多维数组可以因为增强位置(就像有一个单一的指示器解除参照,代替数组的每一维作为锯齿数组的容器)在某些情况下增强性能。另一个优点是整个多维数组可以用单一的new操作符申请而赋值,而锯齿数组需要对每一维进行循环和赋值。注意,尽管Java为分配多维的锯齿数组提供依据句法的整齐的数组长度(在C#术语中是一个矩形数组),循环和多样的分配被虚拟机完成不需要外在的来源。

内部类

java与C#都允许设置内部类,即在一个类内部定义的另一个类。在java中,这些内部类可以访问外部类的静态和非静态成员(除非这个内部类定义为静态的,在这种情况下只能访问外部类的静态成员)。局部内部类可以定义在一个方法中并访问这个方法中声明为final类型的局部变量,匿名局部类允许构造类的实例用来重写类的方法。

C#也提供内部类,与Java不同的是它需要外部类的非静态成员的一个明确引用。同时C#提供匿名类作为一个结构用来访问局部变量和方法(参见事件处理)。局部类和匿名类不能被访问。

部分类

C#使用部分类允许一个类的定义分割在几个源文件中。每一个部分必须用关键字partial标记。作为一个单一的汇编的部分所有的部分都必须提交给编译器。每个部分可以引用其它部分的成员。每个部分都可以实现接口,并且某个部分可以定义一个基类。这个功能在代码生成时非常有用,也就是一个代码发生器提供一部分代码,开发商提供另一部分代码,两种代码在一起编译。因此开发商可以编辑他们的部分代码而不用冒着代码发生器在以后覆盖这部分代码的危险。和类扩展机制不同,部分类在它的部分之间允许循环依赖,因为它们在编译的时候都保证被解决。Java没有类似的概念。

泛型

泛型编程

现在的编程语言都支持泛型编程,但它们却采用了不同的实现方式。

Java中的泛型仅是语言层面上的一种结构,它们只能通过编译器来实现。生成的类文件中所包含的类签名仅由元数据组成(允许编译器对这些新类进行反编译)。运行时并不知道通用类型系统,这意味着JVM只需要进行一小部分的更新便可处理新的类格式。

为了实现这个目标,编译器用泛型类型的上界来替换它们,并且在用到这些泛型的各个地方适当地插入一些“角色”。结果生成的字节码将不包含任何对这些泛型类型的引用或将它们作为参数。这种实现泛型的技术被称作类型擦除。这意味着实际上的类型的信息在运行时不可用,并且强行加入了一些限制,例如不能创建泛型的新实例或数组。(参见Java中的泛型)。

C#采用了另一种实现方式。它对泛型的支持是集成在虚拟执行系统中的,并且最早出现在.NET2.0中。这门语言后来就发展为在执行系统中支持基本泛型的前端。而在Java中,编译器提供了静态类型安全检查,但是,加之又有即时编译器(JIT)加载来核实其正确性。关于泛型类型的信息在运行时完全被保护起来了,并且允许完全的反射和实例化泛型类型。

Java不允许用基本数据类型来声明为泛型类,然而C#却允许不管是引用类型还是值类型被声明为泛型,包括基本数据类型。Java却允许被封装的类型作为泛型类的类型参数来使用(例如:用List<Integer>代替List<int>),但是由于所有这一类的值需要在堆上分配而需付出一定的“代价”。 在Java和C#两者中,泛型的定义都使用了不同的引用类型来分享等效的底层代码,但是对C#来说公共语言运行时(CLR)为值类型的实例化动态的生成优化代码。

符号和特殊功能

特殊功能关键字

关键字 功能,实例
checked,unchecked 在C#里, checked 声明块或表达式可以在运行时检查算术的溢出。
getset C#实现属性作为语言语法的一部分,而且选用相应的get 和set 访问器, 而Java的访问方法, 不是一种语言功能,而是基于方法命名公约的编码方式。
goto C#中支持goto关键字。goto有时候是有用的, 举个例子,实现有限的状态机或者生成的代码, 但是通常建议使用更加合理控制流程的结构化方法(见goto语句的评论)。 Java 允许使用breaks和continues弥补了goto语句的的许多用途。
switch(color)
{
    case Color.Blue:
         Console.WriteLine("Color is blue"); break;
    case Color.DarkBlue:
         Console.WriteLine("Color is dark");
         goto case Color.Blue;
    // ...
}
outref C#支持输出参数和引用参数。这使得c#可以从一个方法返回多个值或者通过引用传递多个值。
strictfp Java 使用关键字 strictfp 确保跨平台时浮点运算的结果保持不变。
switch 在C#里, switch 语句也操作于string型和long型,但是只允许失败的空白语句。 Java switch 语句既不能操作于strings 也不能操作于long的原始类型 但是能通过所有的空白语句(不包括那些含有 'break'的语句)。
throws Java中要求每个方法都要声明它能抛出检测异常或者检测异常的父类。任何方法也可以随意的定义它所抛出的非检测异常,C#中却没有这样的语法规则。
public int readItem() throws java.io.IOException
{
    // ...
}
using C#中的using指令使得对象的Dispose方法(通过IDisposable接口被执行)定义为在代码块执行之后或者在代码块之中的异常被抛出时才被执行。
//创建一个小文件"test.txt",写一个字符串,
//... 并且把它关闭(即使发生了异常)
using (StreamWriter file = new StreamWriter("test.txt"))
{
    file.Write("test");
}
yield C#语言中允许使用yield关键字来表示迭代器。在Java中,迭代器只能用类(可以是匿名的)来定义,且需要很多的样板代码。下面是一个能够读取可迭代的输入(可以是数组)并且返回所有偶数成员的迭代器的例子。
public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
{
    foreach (int i in numbers)
    {
        if (i % 2 == 0)
            yield return i;
    }
}

回调和事件处理

数值应用

多种语言特色的存在是为了充分的支持应用程序在数学和金融领域计算。[1]在这一类中,Java提供关键字strictfp可以在代码段中使浮点运算严格执行。这可以保证运算在所有的平台上都返回相同精确的结果。 与此不同C#为确保十进制小数浮点运算准确,在 decimal 类型中内嵌了这种机制。但在二进制小数浮点运算中舍弃了这种机制(floatdouble)。 在二进制所有的类型中描述十进制数因为不精确会存在舍入误差。所以在金融应用方面十进制小数类型的精确显得很重要。 Java中BigDecimal类也提供了这些特性。任意精度小数算法 (BigDecimal) 和任意精度整数算法 (BigInteger ) 的类为其提供任意精度的数值运算。 尽管有第三方实现了这些类,但是.NET框架(3.5)的现行版本当前并没有提供这些。(参见Arbitrary-precision arithmetic) Java不能为库定义类型(高精度小数、复数等原始类型)提供一个统一标准,为了达到这个目的,C#提供了如下内容:

  • 能够提供方便语法的运算符重载和索引(看下面)。
  • 隐性和显性转换;允许诸如嵌入式int 类型隐性转换为long类型的存在。
  • 值类型和基于值类型的属性;在Java中每个常规类型必须被存放在堆栈中,它对常规类型和存储类型的性能是不利的。

除此之外,C#能用checked和unchecked运算符帮助数学计算,当在一段代码中出现算数溢出时它能够检测出是否能够继续运行。它也提供在内嵌数组的某些应用方面有优势的矩阵。[1]

运算符重载

相比Java,C#包含了许多可数的便利。其中,例如运算符重载、用户自定义类型,许多都被大批的C++程序员所熟悉。 它还具有“外在的成员实现”,这样可以让一个类明确的实现一个接口中的方法,与自己类中的方法分离。或者为分别来自两个接口中,具有相同函数名和签名的函数提供不同的实现。 C#包含了“索引器”,它可以当作是一种特殊的运算符(像C++中的operator[]),或者是用 get/set 访问器来访问类属性。一个索引器用this[]来标明, 并且需要至少一个索引参数,该参数可以为任意类别:

myList[4] = 5;
string name = xmlNode.Attributes["name"];
orders = customerMap[theCustomer];

Java没有提供运算符重载是为了阻止特征滥用,还有为了语言的简单。[2] C#允许运算符重载(以确定的几个限制来确保逻辑上的一致为条件),如果小心地使用,可以使代码更加简洁和易读。


方法

在C#中,方法在默认状态下是非虚拟的,如果希望得到一个虚方法则必须明确地用 virtual 修饰符进行声明,而在Java当中,所有非静态、非私有的方法都是虚方法。虚方法保证被调用的总是该方法最近被重写的那个实现。但是,由于各个重载方法之间不能被正常地进行内联,而使得在方法调用上需要花费一个相当长的运行时间,并且需要通过虚方法列表进行间接的调用。然而,包括Sun公司所推荐的实现方法在内的一些Java虚拟机的实现方法,则会对最普遍被调用的那些虚方法执行内联。在java中,方法在默认状态下是虚拟的。(尽管他们能通过使用“final“修饰符来密封以使他不允许被覆盖)。没有什么办法让subclass或derived class以同样的名字定义一个新的、无关联的方法。 这就会产生一个问题,即当一个基类由一个不同的人定义,这时就有可能出现一个与派生类中已经定义过的一些方法有着相同的名字和标签的新的版本的方法定义。在Java中,这种情况将意味着派生类中的同名方法会隐式的重写基类中的方法,尽管这种结果不是所有设计者的真正意图。为了防止这种版本问题,C#中要求将派生类中需要重写虚方法的部分进行显示的声明。 如果一个方法需要被重写,那么必须指定override修饰符。如果不希望进行方法重写,而且类的设计者仅仅希望引出一个新的方法以影射旧的方法,那么就必须含有new关键字。New关键字和override关键字也避免了由于基类中的protecte方法或public方法在它的某一个派生类中被使用时所带来的问题。Java中重新编译将导致编译器把派生类中的这种方法当做是基类方法的重写,而这可能并不是基类的开发者想要的。

而C#编译器将会把这种方法默认为new关键字已经被指定,但仍会对这种结果发出警告。为了部分地容纳这些版本问题, Java 5.0中引入了@override注释,但为了保护它的向后兼容这种做法不会被当作是强制性的,所以它并不能阻止上述意外的重写情况。然而对于C#中的override关键字,它能有助于确保基类中具有相同签名的方法仍然存在,并且能被正确的重写。

显式接口实现

如果在多个接口中有一个方法(或C #中的属性)具有相同名称和签名,当一个类在实现这些接口时这些重名的成员就会产生冲突。一个解决方法是通过为所有接口实现一个默认共同的方法。如果必须要分开来实现(因为这个方法确实要实现某个特殊的目的,或者是因为各个接口的返回值不一样)。C#显示接口的实现将解决这一问题。在java中消除命名冲突的问题只能通过重构或者是定义更多的接口来避免。C#的显示接口实现还能隐藏底层基础的类和接口,因此使得减少类和接口的复杂性。

开包

当一个函数作为一个参数来传递并为后面的程序调用,这时候会出现一个问题:当这个方法调用了它自己作用域内的变量时会怎样呢?C#中有真正的开包功能,方法的引用会完全的获得它自己作用域范围内的变量。Java中,匿名内部类只能调用到作用域内的常方法,想要调用和更新内部类的话,就必须通过开发人员的手工声明额外的间接的父类来实现。

Lambdas和表达树

C#中的一个特殊类型称" lambdas"。 他们不是方法也不可能构成类接口的部分; 他们只是在功能模块中。 在lambda函数顶部可以定义的一个详细结构体称为表达树。 不管他们是被当成执行函数还是数据结构都起决于编辑器类型,并且不管什么类型变量或参量都要赋值。 Lambdas和表示树在LINQ中都是重要角色。 Java中没有以lambdas或表达树为特色的; 它的主要机制和方法定义是匿名内部类句法。

部分方法

与"部分类"相关 C#允许部分方法在部分类之内指定。 一个部分方法是方法的一个故意声明并且在签名上有一定的约束。 这些约束指定,如果任何类成员没有被定义,那么可以安全地删除。 这个特点允许代码提供大量的监听点(像"模板方法" 中GoF模式)而不用花费多余时间,如果另一个类成员在编译时没有引用它们。而 Java没有对应的概念。


扩展方法

用一个特殊的this指定在一个方法的第一个参数C#允许这个方法扮演成第一个参数类型的一个成员函数。这个外来类的“扩展”是完全句法的。这个扩展方法需要变为静态的,而且定义在一个完全的静态类中。它必须服从在外部静态方法上的任何限定,因此它不能摧毁对象封装。这个“扩展”仅仅是在静态宿主类的命名空间被引进的范围内是活跃的。在java里面,相同的效果可以通过一个另一个类的一般方法得到,但语法将是一个函数调用,而不是方法调用类的C#语法扩展。

发生器方法

发生器方法是一个C#方法 ,这个方法被声明为返回IEnumerable,IEnumerator接口或者这些接口的一般版本,该方法可以用 yield语法实现。它是一个无限的表现形式, 编译器生成的补遗集,可大大减少所需的代码遍历或生成序列;虽然代码只是通过编译器生成。这个特征过去也经常被用作实现无穷大的序列,就像斐波那契数列。java是没有相应的概念。

条件编译

与Java不同,C#使用预编译指令实现了条件编译的功能。它还提供了条件属性,使方法只有在定义了编译常量的时候才被执行。这样一来,只有在定义了DEBUG常量时,Debug.Assert()方法才会执行,断言成为了framework的特色。从1.4版本开始,Java开始提供断言,默认情况下在运行时被关闭,但也可以在调用JVM时使用 "-enableassertions" 或者 "-ea" 打开。

名字空间和源文件

C#的命名空间和C++类似,但不同于Java的包机制,C#命名空间不会以任何方式依赖于源文件的位置,这与Java不同,Java的常规结构要求源文件的位置必须和包目录结构相符。 这两种语言都允许引入类库( 例:import java.util.* ,Java方式),在引入类库后,使用类时就可以直接通过类名引用。不同名字空间或包中可以具有相同名字的类,这样类在使用时可以通过全限定名来引用,或者通过不同的名字只引入必要的类。基于这个问题,Java允许引入单个类(例:import java.util.List)。C#允许在引入类库时 使用语句: using Console = System.Console来为一个类库定义一个新名,它同样允许以using IntList = System.Collections.Generic.List<int>的形式,引入特殊类库。

Java有允许使用某些或所有,具有较短名字的静态方法/领域的静态import句法在类中(例如,允许foo(bar)可以从另一个类中被静态的引进).C#有静态类句法(不与Java的静态内在类混淆),制约类只包含静态方法。 C# 3.0介绍的引伸方法允许用户静态地增加方法到类型(比如,允许foo.bar 的地方可以是研究foo的种类的一个引进的引伸方法)。

Sun Microsystems 软件公司的Java编译器要求,源文件的文件名必须匹配在它里面的唯一的公开类,而C#允许在同一个文件的多公开类,并且投入制约。 C# 2.0和以后的版本允许类定义被分割成几个文件,通过使用在原始代码的关键字partial。

异常处理

Java支持检查异常(checked exception)。C#中只支持非检查异常情况。检查异常强制程序员要么在方法中声明一个异常抛出,要么用try-catch来捕获异常。检查异常可以有助于良好的编程习惯,以确保所有的错误都得到处理。但是Anders Hejlsberg,C#语言首席设计师,和其他人争辩说,他们都在一定程度上对Java进行了拓展但是它们没有被证明是有价值的除了几个程序中的小例子。有一个评论介绍在检查异常时鼓励程序员使用空的catch块,安静的吃掉异常而不是让异常传播到更高水平的常规的异常处理:catch (Exception e) {}.另一种对于检查异常的评论说一个新方法的执行可能会引起意想不到的检查异常被抛出,这是一个合同突破性变化.这可能发生在一个方法实现一个接口或者当一个方法的基本实现改变时,此接口仅声明有限的异常。为这种意料之外的的异常被抛出,一些程序员简单的声明这种方法能抛出任何类型的异常(“抛出异常”),这使检查异常的目的无法实现。不过在某些情况下,异常链(exception chaining)能用于代替,捕获异常后再抛出一个异常异常.例如,如果一个对象访问数据库而不是文件时被改变,那么可以捕获 SQLException异常并且作为IOException异常重新抛出. 因为调用者也许并不需要知道对象内部的工作方式。

在处理try-finally的声明时两种语言也是有差别的。即使try块包含像throwreturn的control-passing语句,finally块也总是要执行。在Java中,这可能导致意外的行为,如果try块最后有return语句返回一个值,然后执行后的finally块也会有return语句返回一个不同的值。 C#利用禁止任何像return或者break的control-passing语句来解决这一问题。 使用try-finally 块的普遍原因是为了保护管理代码的资源,所以珍贵的资源被保证在finally 块中发布。作为句法速记为共同的设想的using语句在C#中处于显著地位,其中using的对象的Dispose()方法总是被调用。

Finally块和未捕捉的异常

(C# 派生的异常特点)对CLI(公共语言基础)的ECMA(欧洲电脑厂商协会)标准指出在堆栈的两次搜索中处理异常。ECMA-355 4th Edition 12.4.2.5 Overview of exception handling首次通过尝试找到一个匹配的 catch 块,如果没有找到就终止该程序。只有当找到匹配的 catch 块时,才会在第二步执行,从而运行干预的finally块。这使得问题在程序状态还没第一次被finally块修改前被诊断;它也消除了当程序在未知状态下,finally块可能有副作用的风险(例如,外部数据的损坏或进一步引发的异常)。

Java语言规范中指出finally块中的代码总会执行即使异常没有被捕获,并且举出实例代码演示期待的结果。[3]

底层的代码

Java Native Interface (JNI)的特征是允许Java代码调用非Java代码。然而,JNI要求被调用的代码必须遵循Java提供的一些在类型和名称上的约定。这种方法是为了适应Java和其他代码更好的交互。这些代码必须是非Java代码,常常是C或者C++代码。JNA提供一种更加方便的Java代码与其他代码的交互,仅仅需要写一些Java编写的接口代码,但是性能会付出一点代价。

另外,第三方类库为JAVA-COM提供桥接,像JACOB (自由软件),J-Integra for COM (专有软件)

.NET平台调用(P/Invoke)通过允许从C#调用微软称之为不受托管代码提供同样的的功能,通过元数据属性程序员可以精确的控制如何调用参数和结果,因此可以避免额外编译代码的需要。平台调用允许几乎完全的对程序的API的访问(像Win32或POSIX)但是限制对c++类库的访问。另外,.NET框架也提供一个.NET-COM网桥,允许对COM组件的的访问就像是访问本地的.NET组件。

C#中还允许程序员禁用正常类型检查和CLR中其他的安全保证功能 ,这样就使得指针变量的使用成为可能。当此功能被使用时,程序员必须用unsafe关键字将相应的代码段进行标记。JNI ,P/Invoke,和“unsafe”的代码段是相当冒险的部分,它揭露了可能的安全漏洞和应用不稳定。使用unsafe的一个优势是,通过P/Invoke或JNI运行于托管运行环境中的代码是让程序员在比较熟悉的C #环境中继续工作以完成某些任务,否则将需要调用非托管代码。使用不安全代码的程序或程序集必须通过进行特殊的转换才能被编译并且将依此被标记。这使得运行时环境在潜在地执行有危险的代码前要采取特别的预防措施。

参考资料

外部链接

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

比较C Sharp和Java 的相关文章

  • Java文本输出中的UTF-8编码问题

    我一直致力于测试高棉语 Unicode Wordbreaker 的各种解决方案 高棉语单词之间没有空格 这使得拼写检查和语法检查变得困难 以及从旧高棉语转换为高棉语 Unicode 我得到了一些源代码 现在在线 http www white
  • 泛型类上的 DebuggerDisplay

    我在应用时遇到问题DebuggerDisplay泛型类的属性 DebuggerDisplay foo class Foo DebuggerDisplay Bar t class Bar
  • dlopen 或 dlclose 未调用信号处理程序

    我在随机时间内收到分段错误 我注册了信号 但发生分段错误时未调用信号处理程序 include
  • 如何在不打开浏览器的情况下查看 Android 应用程序中的网页?

    嘿 我正在开发一个 Android 应用程序 我想连接到该应用程序内的网络 不过 我在某种程度上尝试过 WebView 但它在我的目录中显示的文件很好 但当连接到 google com 时 它显示错误 然后我添加了这个文件
  • 在JAVA中将数据写入.txt文件?

    我想知道是否是在JAVA中将计算的数据写入文本文件 我的 JAVA 代码是一个基于 GUI 的 gpa 计算器 我只想添加一个 JButton 和 ActionListener 它将类名 GPA 点和计算出的 GPA 写入 txt 文件 这
  • 将数字 n 拆分为 k 个不同数字的总和

    我有一个数字 n 我必须将它分成 k 个数字 使得所有 k 个数字都是不同的 k 个数字的总和等于 n 并且 k 最大 例如 如果 n 为 9 则答案应为 1 2 6 如果 n 为 15 则答案应为 1 2 3 4 5 这就是我尝试过的 v
  • 访问结构向量

    我有一个结构 struct OutputStore int myINT string mySTRING 如果我创建一个 OutputStore 类型的数组 如下所示 OutputStore OutputFileData new Output
  • 在 Struts 2 中使用单个文件标签上传多个文件

    我想使用单个 Struts 2 文件标签上传多个文件 就像在 Gmail 中一样 我们使用 CTRL 键来选择多个文件来附加多个文件 我知道如何上传多个文件 但我想使用单个文件标签 我在一个小画廊应用程序中上传多个文件 如果您的操作已设置为
  • 为什么 C++ 元组如此奇怪?

    我通常创建自定义structs将不同类型的值分组在一起时 这通常很好 而且我个人发现命名成员访问更容易阅读 但我想创建一个更通用的 API 在其他语言中广泛使用元组后 我想返回类型的值std tuple但发现它们在 C 中使用比在其他语言中
  • 将数组显式衰减为指针

    最简洁 最惯用的方式是什么明确地将数组衰减为指针 例如 考虑您需要能够指导 SFINAE 或明确过载的情况 template
  • 使用可变参数模板函数计算多个值的平均值

    我正在尝试编写一个函数来确定任意数量参数的平均值 所有参数都具有相同的类型 出于学习目的 我尝试使用可变参数模板函数来做到这一点 这是我到目前为止所拥有的 template
  • 当键位于父类中时,如何将一对多集合映射到连接的子类

    我想将一对多集合映射到子类 但集合的键是父类的属性 目前我正在映射 AbstractFoo Foo 和 Bar 类 如下所示
  • 将 .NET 类库(主要定义 CRUD 操作)公开为服务

    公开现有内容的最佳 有效和最快的方法是什么 类 图书馆 主要定义 CRUD 操作 作为service 周转基金服务 or WCF数据服务 以便它可以与银光 or Ajax 在那儿tools 代码生成器 RAD 工具 哪些可以支持这个 预先感
  • 使用 System.Json 迭代 JSON

    我正在探索 NET 4 5 的功能System Json库 但没有太多文档 而且由于流行的 JSON NET 库 搜索起来相当棘手 我基本上想知道 我如何循环一些 JSON 例如 People Simon Age 25 Steve Age
  • 在运行时将项目添加到 ToolStrip

    您好 我有一个带有 收藏夹 菜单的 ToolStripMenu 我想在运行时在 WinForms 应用程序中添加子项目 我有一个 datagridview 右键单击它会显示一个包含 添加到收藏夹 选项的上下文菜单 当该事件被触发时 我想使用
  • 恐怖分子已弃用

    正在接听另一个问题 https stackoverflow com q 11830514 1468366 我偶然发现了man page http linux die net man 3 herror一个名为的函数herror 看起来很像pe
  • 在 Visual Studio C++ 资源编辑器中导入 png 文件

    我希望能够在 Visual Studio 资源编辑器中导入 png 文件 以便能够在不同的其他项目中使用嵌入的资源 有解决办法吗 我知道它适用于位图 但我对 png 感兴趣 因为即使在较低格式 16x16 或 32x32 上也可以使用 透明
  • 致命:所有操作都需要OperationId。请为路径的“获取”操作添加它

    我正在使用 AutoRest 从 swagger json 生成 api 的客户端 输出是 AutoRest code generation utility cli version 3 0 6187 node v10 16 3 max me
  • 在Java中将32bpp图像转换为16bpp图像

    如何使用 Java 库将 32bpp 图像 ARGB 转换为 16bpp 图像 ARGB 出于我的好奇 在像素级别 这种转换有什么作用 如果我有一个保存像素值 包含所有通道 的 int 值 那么在转换发生后该 int 会有什么不同 32 位
  • 如何在Java中添加两个“卡”的值?

    我正在开发一个项目来模拟二十一点游戏中的第一笔交易 到目前为止 程序创建了两张随机等级 ACE 到 KING 和随机花色的牌 我正在努力创建一个切换表或 if else 梯形图 将两张卡的附加值分配为可变分数 下面的代码从概念上代表了我想要

随机推荐

  • Android Studio之将application工程改成library工程生成aar包

    一 修改application工程的app build gradle脚本 1 将项目由应用工程更改为库工程 apply plugin com android application 更改为 apply plugin com android
  • el-input输入框的那些事

    vue3 element plus ts es6 此帖只为记录开发中遇到的需求 技术问题 坑 1 文本域禁止自由拉伸 1 文本域禁止自由拉伸 el input有一个枚举类型的resize属性 控制拉伸 none both horizonta
  • 相关性模型与回归模型(例题代码)

    一 相关性模型 SPSS 相关性模型涉及到两种最为常用的相关系数 皮尔逊person相关系数 斯皮尔曼spearman等级相关系数 1 皮尔逊相关系数 相关性可视化 总结 1 如果两个变量本身就是线性的关系 那么皮尔逊相关系数绝对值大的就是
  • 系统安装部署系列教程(三):VHD方式安装系统

    普通的系统安装方式需要占用一个分区 假如某个分区有很多富裕空间 而且并不想完全格式化分区 可以考虑使用虚拟磁盘方式 VHD 安装系统 使用VHD方式安装的系统 只会占用一个文件 将来不需要的时候直接删除这个文件即可 而且VHD方式安装系统不
  • python多维list去重

    一维的list去重可以用set list 但是二维的list转set就会报错 unhashable type list 原因是set传进来的是不可哈希的变量 Python中那么哪些是可哈希元素 哪些是不可哈希元素 可哈希的元素有 int f
  • 期权策略篇: 实现买方狂欢,让卖方稳赚不赔的策略

    欢迎来到期权策略篇 实现买方狂欢 让卖方稳赚不赔的策略 今天给大家带来的期权策略比较简单 是我们比较常见的四种单腿期权策略 这四种策略分别是买入看涨期权 买入看跌期权 卖出看涨期权 卖出看跌期权策略 本文来自 期权酱 这四种期权策略相对于之
  • 7.27 总结+复盘

    一 初赛错题解析 第一题 题目 解析 像素位 字节位 字节 故选B 第二题 题目 解析 送命题 不会就是不会 做不会只能感叹自己道行甚浅 B选项是代码托管仓库 第三题 题目 解析 选A没啥好说的 记住就好 好奇怎么实现 请自行搜索 拓展一个
  • 2023更新阿里云服务器租用价格表(超详细)

    阿里云服务器分为云服务器ECS和轻量应用服务器 云服务器u1公网带宽可选1M到5M 系统盘为ESSD云盘40GB起 CPU内存配置可选2核2G 2核4G 4核8G 8核16G等配置 云服务器s6公网带宽可选1M到5M 系统盘40G起可选高效
  • 运放单的电源供电和双电源供电

    我们经常看到很多非常经典的运算放大器应用图集 但是他们都建立在双电源的基 础上 很多时候 电路的设计者必须用单电源供电 但是他们不知道该如何将双电源 的电路转换成单电源电路 在设计单电源电路时需要比双电源电路更加小 1 1 电源供电和单电源
  • vue后台管理动态路由-页面刷新之后跳转到默认页面的问题

    路由我们是用公共路由 动态路由 写的过程中发现 在动态路由的页面刷新页面后跳转到了默认页面 也就是我们设置的 path pathMatch redirect dashboard hidden true 本来这行代码我是写到公共路由里面了 就
  • 技术爆炸已至,AIGC(AI-Generated Content)带来内容产业全新格局

    公众号 做棵大树 欢迎关注一起进步 最近 在元宇宙概念大火的同时 人工智能技术也正在迎来新一轮的爆发 Chat GPT AIGC AI Generated Content 人工智能生成内容 正在成为一个新的风口 AIGC 即人工智能生成内容
  • Proteus元件库元件名称及中英对照表

    以下是具体内容 AND 与门 ANTENNA 天线 BATTERY 直流电源 BELL 铃 钟 BVC 同轴电缆接插件 BRIDEG 1 整流桥 二极管 BRIDEG 2 整流桥 集成块 BUFFER 缓冲器 BUZZER 蜂鸣器 CAP
  • 改进YOLO系列:4.添加ACmix注意力机制

    添加ACmix注意力机制 1 ACmix注意力机制论文 ACmix注意力机制原理 ACmix注意力机制的配置 common py配置 yolo py配置 yaml文件配置 1 ACmix注意力机制论文 论文题目 On the Integra
  • 上帝掷骰子吗--量子物理史话

    上帝掷骰子吗 量子物理史话 第一章黄金时代 一 我们的故事要从1887年的德国开始 位于莱茵河边的卡尔斯鲁厄是一座风景秀丽的城市 在它的城中心 矗立着著名的18世纪的宫殿 郁郁葱葱的森林和温暖的气候也使得这座小城成为了欧洲的一个旅游名胜 然
  • C++智能指针简单剖析

    转自 https www cnblogs com lanxuezaipiao p 4132096 html 导读 最近在补看 C Primer Plus 第六版 这的确是本好书 其中关于智能指针的章节解析的非常清晰 一解我以前的多处困惑 C
  • 如何有效地进行代码 Review

    前言 作为公司代码委员会 golang 分会的理事 我 review 了很多代码 看了很多别人的 review 评论 发现不少同学 code review 与写出好代码的水平有待提高 在这里 想分享一下我的一些理念和思路 为什么技术人员包括
  • select下拉框赋值和取值

    jq的select常用的方法 一 下拉框赋值 1 已创建select的下拉框 选中option的value为jquery 例 szfs val jquery 选中option的text为jquery 例 select id option t
  • 五分钟搭建Jetbrains家族IDE授权服务器

    作为Java码农 IntelliJ IDEA可谓是N0 1的开发环境了 对框架的支持 界面 插件都是比较方便的 大大加快了开发的速度以及开发的乐趣 酷炫的界面也能大大的装一个逼 虽然这里教大家搭建授权服务器 但是月入1狗的同志还是支持一下人
  • LVGL学习笔记

    文章目录 前言 一 软件安装 1 VSCode安装 2 MSYS2安装 二 配置环境 1 添加环境变量 2 配置msys2环境 3 配置VSCode 三 运行lvgl示例 前言 最近需要使用LittlevGL 以下简称lvgl 做ARM开发
  • 比较C Sharp和Java

    本文对比C 与Java编程语言 因为这两种语言都具有自动垃圾回收以及运行时编译执行的特点 并且他们的语法都是继承自C语言 C 因此二者有个很多相似之处 但由于C 也被描述为一个C 和Java的混合体 并添加了一些新特性 引入了一些变化 因此