这不是什么是装箱和拆箱的问题,而是为什么像Java和C#这样的语言需要呢?
我非常熟悉C++,STL和Boost.
在C++中,我可以很容易地写出这样的东西,
std::vector<double> dummy;
Run Code Online (Sandbox Code Playgroud)
我有一些Java经验,但我真的很惊讶,因为我必须写这样的东西,
ArrayList<Double> dummy = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)
我的问题,为什么它应该是一个对象,在谈论泛型时,在技术上如此难以包含原始类型?
我有这段代码:
public void someMethod(String id) {
someOtherMethod(Integer.valueOf(id));
}
public void someOtherMethod(int id) {
// do something with id
}
Run Code Online (Sandbox Code Playgroud)
在第二行,Findbugs抛出了这个异常:
用于解析基元的装箱/拆箱
当我只是调用Integer.valueOf()/我该如何解决这个问题时,为什么Findbugs抱怨这个?
我想知道如何比较两个盒装整数(可以是有符号或无符号)以保证相等.
例如,看看这个场景:
// case #1
object int1 = (int)50505;
object int2 = (int)50505;
bool success12 = int1.Equals(int2); // this is true. (pass)
// case #2
int int3 = (int)50505;
ushort int4 = (ushort)50505;
bool success34 = int3.Equals(int4); // this is also true. (pass)
// case #3
object int5 = (int)50505;
object int6 = (ushort)50505;
bool success56 = int5.Equals(int6); // this is false. (fail)
Run Code Online (Sandbox Code Playgroud)
我很难理解如何以这种方式可靠地比较盒装整数类型.直到运行时我才会知道它们是什么,我不能把它们都放到long,因为一个可能是一个ulong.我也不能将它们都转换成两者,ulong因为一个可能是负面的.
我能想到的最好的想法就是试错,直到找到一个普通类型或者可以排除它们不相等,这不是一个理想的解决方案.
我最近的另一个C#面试问题是,如果我知道Boxing和Unboxing是什么.我解释了堆上的值类型和Heap上的引用类型.当一个值转换为引用类型时,我们将其称为装箱,反之亦然.
然后他让我计算一下:
int i = 20;
object j = i;
j = 50;
Run Code Online (Sandbox Code Playgroud)
什么是i?
我把它搞砸了,然后说了50,它实际上是20.现在我想明白为什么,但是当我玩不同的组合时,我很惊讶地看到这个:
Object a = 1; // Boxing
Object b = a; // referencing the pointer on stack to both objects on heap
a = 2; // Boxing
Run Code Online (Sandbox Code Playgroud)
我期待也能看到b == 2,但事实并非如此,为什么?是因为第二次拳击会破坏并替换a堆上的整个对象吗?
因为如果我这样做,那很好:
public class TT
{
public int x;
}
TT t = new TT();
t.x = 1;
TT t2 = new TT();
t2.x = 2;
t = t2;
t.x = …Run Code Online (Sandbox Code Playgroud) 我做了一些ref关键字测试,有一个认为我无法理解:
static void Test(ref int a, ref int b)
{
Console.WriteLine(Int32.ReferenceEquals(a,b));
}
static void Main(string[] args)
{
int a = 4;
Test(ref a, ref a);
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
为什么显示此代码False?我知道这int是一个值类型,但在这里它应该传递对同一个对象的引用.
这是我直到今天才注意到的事情.显然,当执行基于相等的操作时Tuple<T>,很多使用的元组类(Tuple<T1, T2>等)的.NET实现会导致值类型的装箱惩罚.
以下是该类在框架中的实现方式(来自ILSpy的源代码):
public class Tuple<T1, T2> : IStructuralEquatable
{
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public Tuple(T1 item1, T2 item2)
{
this.Item1 = item1;
this.Item2 = item2;
}
public override bool Equals(object obj)
{
return this.Equals(obj, EqualityComparer<object>.Default);
}
public override int GetHashCode()
{
return this.GetHashCode(EqualityComparer<object>.Default);
}
public bool Equals(object obj, IEqualityComparer comparer)
{
if (obj == null)
{
return false;
}
var tuple …Run Code Online (Sandbox Code Playgroud) 我有一段代码需要我理解:
public static void main(String[] args) {
Character c = new Character('a');
Character cy = new Character('a');
char cx = 'a';
System.out.println(c == cx);
System.out.println(cx == cy);
System.out.println(c == cy);
}
Run Code Online (Sandbox Code Playgroud)
输出:
true
true
false
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么只有第三个陈述失败了.
编辑:这个问题.equals与==原始与对象比较的vs 问题不同.
我正在寻找一种编写代码来测试值是否已装箱的方法.
我的初步调查表明,.NET不顾一切地隐瞒事实,这意味着GetType()并IsValueType没有揭示盒装值和未装箱值之间的差异.例如,在下面的LinqPad C#表情,我有信心o1在盒装和i1没有盒装,但是我想一个方法来测试它的代码,或者退而求其次,就无从知道肯定看任何变量时或值,即使它的类型是"动态"或"对象",无论是盒装还是不盒装.
有什么建议?
// boxed? -- no way to tell from these answers!
object o1 = 123;
o1.GetType().Dump("o1.GetType()");
o1.GetType().IsValueType.Dump("o1.GetType().IsValueType");
// not boxed? -- no way to tell from these answers!
int i1 = 123;
i1.GetType().Dump("i1.GetType()");
i1.GetType().IsValueType.Dump("i1.GetType().IsValueType");
Run Code Online (Sandbox Code Playgroud) 我只是参与Stack Overflow问题.NET中的所有内容都是对象吗?.
并且一张海报(在接受的答案的评论中)似乎认为对值类型执行方法调用导致拳击.他向我指出了Boxing和Unboxing(C#编程指南),它没有明确指出我们描述的用例.
我不是一个信任单一来源的人,所以我只是希望得到关于这个问题的进一步反馈.我的直觉是没有拳击,但我的直觉确实很糟糕.:d
进一步阐述:
我使用的例子是:
int x = 5;
string s = x.ToString(); // Boxing??
Run Code Online (Sandbox Code Playgroud)
如果有问题的结构覆盖从对象继承的方法,则不会发生拳击,如此处所接受的答案所述.
但是,如果结构不覆盖该方法,则在callvirt之前执行"约束" CIL命令.根据文档,OpCodes.Constrained Field,这导致拳击:
如果thisType是一个值类型而thisType没有实现方法,则ptr被解除引用,装箱,并作为'this'指针传递给callvirt方法指令.
情况1
static void call(Integer i) {
System.out.println("hi" + i);
}
static void call(int i) {
System.out.println("hello" + i);
}
public static void main(String... args) {
call(10);
}
Run Code Online (Sandbox Code Playgroud)
案例1的输出:hello10
案例2
static void call(Integer... i) {
System.out.println("hi" + i);
}
static void call(int... i) {
System.out.println("hello" + i);
}
public static void main(String... args) {
call(10);
}
Run Code Online (Sandbox Code Playgroud)
显示编译错误reference to call ambiguous.但是,我无法理解.为什么?但是,当我评论出任何call()方法时Case 2,它的工作正常.任何人都可以帮助我理解,这里发生了什么?