当我遇到Joel Spolsky时,我正在阅读更多关于Joel on Software的文章,说明一种特定类型的程序员知道a 和Java/C#(面向对象编程语言)之间的区别.int
Integer
那么区别是什么呢?
我知道,如果你将盒装原始Integer与常量进行比较,例如:
Integer a = 4;
if (a < 5)
Run Code Online (Sandbox Code Playgroud)
a
将自动取消装箱,比较将起作用.
但是,当您比较两个盒装Integers
并希望比较相等或小于/大于?时会发生什么?
Integer a = 4;
Integer b = 5;
if (a == b)
Run Code Online (Sandbox Code Playgroud)
以上代码是否会导致检查它们是否是同一个对象,还是会在这种情况下自动取消装箱?
关于什么:
Integer a = 4;
Integer b = 5;
if (a < b)
Run Code Online (Sandbox Code Playgroud)
?
观察这种情况让我非常困惑:
Integer i = null;
String str = null;
if (i == null) { //Nothing happens
...
}
if (str == null) { //Nothing happens
}
if (i == 0) { //NullPointerException
...
}
if (str == "0") { //Nothing happens
...
}
Run Code Online (Sandbox Code Playgroud)
因此,我认为首先执行装箱操作(即java尝试从中提取int值null
),并且比较操作具有较低的优先级,这就是抛出异常的原因.
问题是:为什么在Java中以这种方式实现它?为什么拳击优先于比较参考?或者为什么他们没有null
在拳击前实施验证?
目前,当NullPointerException
使用包装的基元抛出它时看起来不一致,并且不会抛出真正的对象类型.
boolean
当方法boolean Boolean.getBoolean(String name)
弹出自动完成窗口时,我最近尝试将字符串文字转换为a .之后还boolean Boolean.parseBoolean(String s)
出现了另一种方法(),这使我找到了解这两者之间的差异,因为他们似乎都做了同样的事情.
事实证明,Boolean.getBoolean(String name)
真正做的是检查是否存在System
给定名称的属性(!)以及它的值是否为true
.我认为这是非常误导的,因为我绝对没想到一个方法Boolean
实际上正在调用System.getProperty
,只是通过查看方法签名,它肯定看起来(至少对我来说)它应该用来解析一个String
作为boolean
.当然,javadoc清楚地说明了这一点,但我仍然认为该方法有一个误导性的名称,并且它不在正确的位置.其他原始类型的包装器,Integer
也有类似的方法.
此外,它似乎不是一个非常有用的方法属于基础API,因为我认为有类似的东西并不常见-Darg=true
.对于Java职位面试来说,这可能是一个很好的问题:"输出是Boolean.getBoolean("true")
什么?".我相信这些方法更合适的地方就是在System
课堂上,例如getPropertyAsBoolean
; 但同样,我仍然认为在基础API中使用这些方法是不必要的.将它们放在类似于Properties
类的东西中是有意义的,这种类型的转换很常见.
你觉得这一切怎么样?此外,如果你知道另一个"尴尬"的方法,请发布它.
NB我知道我可以使用Boolean.valueOf
或Boolean.parseBoolean
将字符串文字转换为a boolean
,但我只是想讨论API设计.
请考虑以下代码段:
int i = 99999999;
byte b = 99;
short s = 9999;
Integer ii = Integer.valueOf(9); // should be within cache
System.out.println(new Integer(i) == i); // "true"
System.out.println(new Integer(b) == b); // "true"
System.out.println(new Integer(s) == s); // "true"
System.out.println(new Integer(ii) == ii); // "false"
Run Code Online (Sandbox Code Playgroud)
很明显为什么最后一行总是打印出来"false"
:我们正在使用==
引用标识比较,而new
对象永远不会是==
已经存在的对象.
问题是前三行:那些比较保证在原语上int
,Integer
自动取消装箱?是否存在基元将被自动装箱的情况,并且执行参考标识比较?(那就是全部false
!)
运行以下Java代码:
boolean b = false;
Double d1 = 0d;
Double d2 = null;
Double d = b ? d1.doubleValue() : d2;
Run Code Online (Sandbox Code Playgroud)
为什么会出现NullPointerException?
"API设计就像性:做出一个错误并在你的余生中支持它" (Josh Bloch在Twitter上)
Java库中存在许多设计错误.Stack extends Vector
(讨论),我们无法在不造成破损的情况下解决这个问题.我们可以尝试弃用Integer.getInteger
(讨论),但它可能会永远存在.
尽管如此,某些类型的改装可以在不造成破损的情况下完成.
有效的Java第2版,第18项:首选接口到抽象类:现有的类可以很容易地进行改进,以实现新的接口".
例如:String implements CharSequence
,Vector implements List
,等.
有效的Java第2版,第42项:明智地使用varargs:您可以改进现有方法,该方法将数组作为其最终参数,而不是对现有客户端采取varags.
一个着名的例子是Arrays.asList
引起混淆(讨论),但没有破坏.
这个问题是关于不同类型的改造:
void
不破坏现有代码的情况下改进返回方法的方法?我最初的预感指向是,因为:
void
退货换货是合法的(但不是相反!)Class.getMethod
也不会在返回类型上区分但是,我希望听到其他在Java/API设计方面经验丰富的人进行更全面的分析.
正如标题中所建议的那样,一个动机是促进流畅的界面风格编程.
考虑这个简单的代码片段,它打印一个混洗的名称列表:
List<String> names = Arrays.asList("Eenie", "Meenie", "Miny", "Moe");
Collections.shuffle(names);
System.out.println(names);
// prints e.g. [Miny, Moe, Meenie, Eenie]
Run Code Online (Sandbox Code Playgroud)
已经Collections.shuffle(List)
被宣布为返回输入列表中,我们可以这样写:
System.out.println(
Collections.shuffle(Arrays.asList("Eenie", …
Run Code Online (Sandbox Code Playgroud) 我在Java中有一个带方法签名的函数
public void myMethod (int someInt, String someString)
Run Code Online (Sandbox Code Playgroud)
在我的抽象类中,我用方法覆盖了它
public void myMethod (Integer someInt, String someString)
Run Code Online (Sandbox Code Playgroud)
过度骑行不起作用.这是不一致吗?我认为自动装箱也适用于方法签名覆盖.
我是Java的新手.在编写Map <>时,我发现声明Map<int, int>
是语法错误,而且没问题Map<Integer, Integer>
.是否只能在Java中实例化对象类型的泛型,而不是原语?如果是这样,基元的装箱/拆箱会有明显的性能损失吗?
参考:http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html
"如果你的程序尝试autounbox null,它将抛出NullPointerException."
如果尝试将null赋给布尔值,javac将给出编译时错误.说得通.尽管如此,将null赋给布尔值也是如此.我猜也是有道理的.
但是让我们考虑一下这样一个事实:当你尝试autounbox null时你会得到一个NPE.这意味着你不能在没有空值检查或异常处理的情况下安全地对布尔值执行布尔运算.在整数上进行数学运算也是如此.
很长一段时间,我是java1.5 +中自动装箱的粉丝,因为我认为它让java更接近真正的面向对象.但是,昨晚遇到这个问题之后,我得说我认为这很糟糕.当我尝试使用未初始化的原语时,编译器给我一个错误是一件好事.如果我输了,我不想使用自动装箱.
我想我可能误解了自动装箱的问题,但与此同时我永远不会接受布尔值应该能够有3个值.谁有人解释这个?我没有得到什么?
分配值而不使用通常的表示法,例如"this.<Double> getAnything(int flag)"
private <T> T getAnything(int flag) {
Object o = null;
if (flag==0)
o=new String("NewString");
else if (flag==1)
o=new Double(0D);
return (T)o;
}
private void someMethod() {
String s = getAnything(0);
Double d = getAnything(1);
}
Run Code Online (Sandbox Code Playgroud)
在过去,只有方法上的返回对象和接收类型上的简单强制转换就足够了,因此在接收器对象上缺少通用符号,它更加相似和快速写入,还有其他任何提示吗?
该程序将使用for循环计算4个考试的平均成绩,方法是一次一个地提示用户输入考试成绩,然后计算平均值并显示结果.
public class ExamsFor4 {
public static void main(String[] arguments) {
int inputNumber; // One of the exams input by the user.
int sum = 0; // The sum of the exams.
int i; // Number of exams.
Double Avg; // The average of the exams.
TextIO.put("Please enter the first exam: "); // get the first exam.
inputNumber = TextIO.getlnInt();
for ( i = 1; i <= 4; i++ ) {
sum += inputNumber; // Add inputNumber to running sum. …
Run Code Online (Sandbox Code Playgroud) java ×13
autoboxing ×5
generics ×2
integer ×2
api-design ×1
boxing ×1
c# ×1
comparison ×1
int ×1
jvm ×1
math ×1
methods ×1
primitive ×1
unboxing ×1
wrapper ×1