我今天偶然发现了这个问题:
class Test {
char ok = '\n';
char okAsWell = '\u000B';
char error = '\u000A';
}
Run Code Online (Sandbox Code Playgroud)
它不编译:
第4行中的字符常量无效.
编译器似乎坚持要我写'\n'而不是.我没有理由这样做,但它很烦人.
有没有为什么有一个特殊的符号字符(比如一个合乎逻辑的解释\t
,\n
,\r
)必须要在Java源代码这种形式表达?
有一些东西让我对Java内存模型感到困扰(如果我甚至正确理解了所有内容).如果有两个线程A和B,则无法保证B将看到A写入的值,除非A和B在同一监视器上同步.
对于保证线程之间的高速缓存一致性的任何系统体系结构,没有问题.但是,如果架构不支持硬件中的缓存一致性,这实质上意味着每当线程进入监视器时,之前所做的所有内存更改都必须提交到主内存,并且缓存必须无效.它需要是整个数据缓存,而不仅仅是几行,因为监视器没有信息,它在内存中保存哪些变量.但这肯定会影响任何需要频繁同步的应用程序的性能(特别是像短时间运行的作业队列这样的事情).那么Java可以在没有硬件缓存一致性的架构上合理地工作吗?如果没有,为什么内存模型不能提供更强的可见性保证?如果语言需要监视器保护的信息,那会不会更有效率?
正如我所看到的,内存模型给我们带来了两个世界中最糟糕的,绝对需要同步,即使硬件中保证了高速缓存一致性,另一方面,非相干体系结构上的性能不佳(完全高速缓存刷新).因此,它不应该更严格(需要信息由监视器保护)或更多地丢失和限制缓存一致的架构的潜在平台?
就像现在一样,它对我来说没有多大意义.有人可以清楚为什么选择这种特定的记忆模型吗?
编辑:回想起来,我对严格和失败的使用是一个糟糕的选择.我对"保证较少"的情况使用"严格",而对相反则"丢失".为了避免混淆,最好用更强或更弱的保证来说话.
在官方Oracle JDK 1.7.0下运行时,使用Microsoft JDBC-Driver 3.0版从SQLServer2008检索DATE类型的列时,我会产生奇怪的效果.主机操作系统是Windows Server 2003.
所有日期栏,为检索两个天过去相对于实际存储在列中的值.
我编写了一个最小的代码示例,测试了这个(测试表和数据):
CREATE TABLE Java7DateTest (
dateColumn DATE
);
INSERT INTO Java7DateTest VALUES('2011-10-10');
Run Code Online (Sandbox Code Playgroud)
码:
public class Java7SQLDateTest {
public static void main(final String[] argv) {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection connection = DriverManager.getConnection(
"jdbc:sqlserver://192.168.0.1:1433;databaseName=dbNameHere",
"user", "password");
PreparedStatement statement = connection.prepareStatement("SELECT * FROM Java7DateTest");
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
final java.sql.Date date = resultSet.getDate("dateColumn");
final String str = resultSet.getString("dateColumn");
System.out.println(date + " (raw: " + str + ")");
} …
Run Code Online (Sandbox Code Playgroud) 什么是比较两个浮点值以获得精确相等的优雅,可读和非冗长的方法?
听起来很简单,这是一个邪恶的问题.该==
运营商没有得到楠所做的工作,也有特殊待遇的零:
(+0.0 == -0.0) -> true
Double.NaN == Double.NaN -> false
Run Code Online (Sandbox Code Playgroud)
但我想确定两个值是否完全相同(但我不关心不同的NaN模式,因此任何NaN ==任何其他NaN - > true).
我可以用这个丑陋的Monster代码做到这一点:
Double.doubleToLongBits(a) == Double.doubleToLongBits(b)
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来写这个(并使意图明显)?
我试图在对话框中显示打印机位置.但令我惊讶的是,没有任何打印服务似乎具有位置属性 - 尽管我验证了我的一些打印机确实在Windows打印机控制面板中显示了一个位置.
我使用此代码打印位置(它始终为位置打印"null").我的Java版本是1.7.0_21:
public class PrintLocation {
public static void main(String[] argv) {
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : services) {
Object location = service.getAttribute(PrinterLocation.class);
System.out.println(service.getName() + " - " + location);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是不是由JRE支持/实施还是我在这里做错了什么?如何获取打印机的位置?
编辑:我的机器上的输出是:
\\srv51\SIR-2725-01_KX_color - null
\\srv51\SIR-2725-01_KX_sw - null
Microsoft XPS Document Writer - null
Microsoft Office Document Image Writer - null
FreePDF XP - null
Run Code Online (Sandbox Code Playgroud)
EDIT2:正如所建议的,我打印出所有属性:
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
for (PrintService service : services) {
PrintServiceAttributeSet attrs = service.getAttributes(); …
Run Code Online (Sandbox Code Playgroud) 我正在寻找在任意位置提取任意长度(0 <=长度<= 16)的(无符号)位序列的最有效方法.骨架类显示了我当前的实现如何处理问题:
public abstract class BitArray {
byte[] bytes = new byte[2048];
int bitGet;
public BitArray() {
}
public void readNextBlock(int initialBitGet, int count) {
// substitute for reading from an input stream
for (int i=(initialBitGet>>3); i<=count; ++i) {
bytes[i] = (byte) i;
}
prepareBitGet(initialBitGet, count);
}
public abstract void prepareBitGet(int initialBitGet, int count);
public abstract int getBits(int count);
static class Version0 extends BitArray {
public void prepareBitGet(int initialBitGet, int count) {
bitGet = initialBitGet;
}
public int getBits(int …
Run Code Online (Sandbox Code Playgroud) 我有一个JList,并希望用户能够使用drag-n-drop重新排序列表中的元素(使用我自己的ListModel和ListCellRenderer,如果这有任何区别).我需要创建哪些对象,以及如何处理该操作?
我一直想知道如何最好地为一系列类实现equals(),这些类都实现了相同的接口(并且客户端应该只与所述接口一起工作,从不知道实现类).
我还没有编写自己的具体示例,但JDK中有两个示例 - java.lang.Number和java.lang.CharSequence来说明决策:
boolean b1 = new Byte(0).equals( new Integer(0) ) );
Run Code Online (Sandbox Code Playgroud)
或者使用CharSequence
boolean b2 = "".equals(new StringBuilder());
Run Code Online (Sandbox Code Playgroud)
理想情况下,您是否希望那些评估为真或不合适?这两种类型都实现了相同的数据类型接口,并且作为使用Numbers(resp.CharSequences)实例的客户端,如果equals将比较接口类型而不是实现类型,那么我将有更轻松的生活.
现在这不是一个理想的例子,因为JDK向公众公开了实现类型,但是假设我们不必维持与已经存在的内容的兼容性 - 从设计者的角度来看:应该等于检查接口还是它更好的方式,检查实施?
注意:我理解在实践中检查与接口的相等性是非常难以实际正确实现的,并且由于相等的接口也需要返回相同的hashCode(),因此它变得更加棘手.但是,这些都只是在实施的障碍,采取例如CharSequence的,虽然界面是非常小的,平等的检查所需的一切存在内部消除揭示实施的内部结构(所以它主要是能够正确实施,甚至不知道未来提前实施).但我对设计方面更感兴趣,而不是如何实际实现它.我不会仅根据实施的难度来决定.
是否有任何完全符合IEEE的Java754r实现可用于Java,它们支持Java选择省略的所有功能(或者更确切地说是高级语言,如省略):
在任何人弄错之前澄清:我不是在寻找JVM来为上面提供任何支持,只是在软件中实现类型和操作的一些类,基本上是已经存在的原始包装类的样式Float /双.
具体用例:二进制数据有一个抽象,广泛用于处理任意大小的二进制blob.由于抽象是在没有关于VM 之外的事情的情况下创建的,因此现有实现依赖于垃圾收集器的生命周期.
现在我想添加一个使用堆外存储的新实现(例如在临时文件中).由于存在许多使用抽象的现有代码,因此引入用于显式生命周期管理的其他方法是不切实际的,我不能使用每个客户端用例来重写以确保它们管理新的生命周期要求.
我可以想到两种解决方案,但无法确定哪种方法更好:
a.)使用finalize()来管理相关资源的生命周期(例如,在finalize中删除临时文件.这似乎很容易实现.
b.)使用引用队列和java.lang.Reference(但是哪一个,弱或幻像?)和一些额外的对象,在引用入队时删除文件.这似乎需要更多的工作来实现,我需要不仅创建新的实现,而是分离其清理数据并确保清理对象在暴露给用户的对象之前不能进行GC .
c.)我还没有其他方法吗?
我应该采取哪种方法(为什么我更喜欢它)?也欢迎实施提示.
编辑:所需的可靠性程度 - 对于我的目的,如果在VM突然终止时未清除临时文件,则完全正常.主要关注的是,当VM运行时,它可以很好地填充本地磁盘(在几天的过程中)与临时文件(这在我身上发生了真正的apache TIKA,它在提取文本时创建了临时文件从某些文档类型来看,zip文件是我认为的罪魁祸首.我在机器上安排了定期清理工作,因此如果文件因清理而丢失,则并不意味着世界末日 - 只要它在短时间内不会定期发生.
据我所知,finalize()适用于Oracale JRE.如果我正确解释了javadocs,引用必须按照文档记录工作(在抛出OutOfMemoryError之前,不能清除只有软/弱可达的引用对象).这意味着当VM可能决定不长时间回收特定对象时,它必须在堆满时最新.反过来,这意味着堆上只存在有限数量的基于文件的blob.VM必须在某些时候清理它们,否则它将完全耗尽内存.或者是否有任何漏洞允许VM在没有清除引用的情况下运行OOM(假设它们不再被严格引用)?
Edit2:就此而言,就此而言,finalize()和Reference应该足够可靠,但我收集Reference可能是更好的解决方案,因为它与GC的交互无法恢复死对象,从而无法恢复其性能影响应该少些?
编辑3:依赖于VM终止或启动(关闭挂钩或类似)的解决方案方法对我没用,因为通常VM会运行很长一段时间(服务器环境).