Java字符谜题解惑

简介: Java字符谜题解惑

本来是应该写java技术类问题以及解决方案的,但是近几天没遇到什么有价值的问题,就分享一些有趣的东西。在学习的过程中,我们更多的注重于应用上,忽略了过程,虽然说结果很重要,但明白其中的过程,知道其中的原理可以让我们对结果更好的把控。下面分享一个java小知识。

畜牧场

George Orwell的《畜牧场(Animal Farm)》一书的读者可能还记得老上校的宣言:“所有的动物都是平等的。”下面的Java程序试图要测试这项宣言。那么,它将打印出什么呢?

public classAnimalFarm{

   public static void main(String[] args){

       final String pig = "length:10";

       final String dog = "length: "+ pig.length();

       System.out. println("Animals areequal: "

                           + pig == dog);

   }

}

   对该程序的表面分析可能会认为它应该打印出Animal are equal:true。毕竟,pigdog都是finalstring类型变量,它们都被初始化为字符序列“length: 10”。换句话说,被pigdog引用的字符串是且永远是彼此相等的。然而,==操作符测试的是这两个对象引用是否正好引用到了相同的对象上。在本例中,它们并非引用到了相同的对象上。

   你可能知道String类型的编译期常量是内存限定的。换句话说,任何两个String类型的常量表达式,如果标明的是相同的字符序列,那么它们就用相同的对象引用来表示。如果用常量表达式来初始化pigdog,那么它们确实会指向相同的对象,但是dog并不是用常量表达式初始化的。既然语言已经对在常量表达式中允许出现的操作作出了限制,而方法调用又不在其中,那么,这个程序就应该打印Animal are equal:false,对吗?

   嗯,实际上不对。如果你运行该程序,你就会发现它打印的只是false,并没有其它的任何东西。它没有打印Animal are equal:。它怎么会不打印这个字符串字面常量呢?毕竟打印它才是正确的呀!谜题11的解谜方案包含了一条暗示:+ 操作符,不论是用作加法还是字符串连接操作,它都比 == 操作符的优先级高。因此,println方法的参数是按照下面的方式计算的:

System.out.println(("Animalsare equal: " + pig) == dog);

    这个布尔表达式的值当然是false,它正是该程序的所打印的输出。

   有一个肯定能够避免此类窘境的方法:在使用字符串连接操作符时,总是将非平凡的操作数用括号括起来。更一般地讲,当你不能确定你是否需要括号时,应该选择稳妥地做法,将它们括起来。如果你在println语句中像下面这样把比较部分括起来,它将产生所期望的输出Animals areequal: false

System.out.println("Animalsare equal: " + (pig == dog));

   可以论证,该程序仍然有问题。

   如果可以的话,你的代码不应该依赖于字符串常量的内存限定机制。内存限定机制只是设计用来减少虚拟机内存占有量的,它并不是作为程序员可以使用的一种工具而设计的。就像这个谜题所展示的,哪一个表达式会产生字符串常量并非总是很显而易见。

   更糟的是,如果你的代码依赖于内存限定机制实现操作的正确性,那么你就必须仔细地了解哪些域和参数必定是内存限定的。编译器不会帮你去检查这些不变量,因为内存限定的和不限定的字符串使用相同的类型(String)来表示的。这些因在内存中限定字符串失败而导致的bug是非常难以探测到的。

   在比较对象引用时,你应该优先使用equals方法而不是 == 操作符,除非你需要比较的是对象的标识而不是对象的值。通过把这个教训应用到我们的程序中,我们给出了下面的println语句,这才是它应该具有的模样。很明显,在用这种方式订正了该程序之后,它将打印出true

System.out.println("Animalsare equal: " + pig.equals(dog));

   这个谜题对语言设计者来说有两个教训。

字符串连接的优先级不应该和加法一样。这意味着重载 + 操作符来执行字符串连接是有问题的,就像在谜题11中提到的一样。

还有就是,对于不可修改的类型,例如String,其引用的等价性比值的等价性更加让人感到迷惑。也许 == 操作符在被应用于不可修改的类型时应该执行值比较。要实现这一点,一种方法是将 == 操作符作为equals方法的简便写法,并提供一个单独的类似于System.identityHashCode的方法来执行引用标识的比较。

 

两个人猜数问题

教授选出两个从29的数,把它们的和告诉学生甲,把它们的积告诉学生乙,让他们轮流猜这两个数,甲说:“我猜不出”,乙说:“我猜不出”,甲说:“我猜到了”,   乙说:“我也猜到了”,问这两个数是多少?

解答:34。设两个数为n1n2n1> =n2,甲听到的数为n=n1 n2,乙听到的数为m=n1*n2,证明n1=3n2=4是唯一解。证明:要证以上命题为真,不妨先证n=7

1)必要性:

  i)   n> 5  是显然的,因为n <4不可能,n=4或者n=5甲都不可能回答不知道

  ii)   n> 6  因为如果n=6的话,那么甲虽然不知道(不确定2 4还是3 3)但是无论是24还是33乙都不可能说不知道(m=8或者m=9的话乙说不知道是没有道理的)

  iii)   n <8  因为如果n> =8的话,就可以将n分解成   n=4 x     n=6 (x-2),那么m可以是4x也可以是6(x-2)4x=6(x-2)的必要条件是x=6n=10,那样n又可以分解成8 2,所以总之当n> =8时,n至少可以分解成两种不同的合数之和,这样乙说不知道的时候,甲就没有理由马上说知道。以上证明了必要性。

2)充分性

   当n=7时,n可以分解成2 53 4

   显然2 5不符合题意,舍去,容易判断出3 4符合题意,m=12,证毕

   于是得到n=7   m=12  n1=3   n2=4是唯一解。

 

这些知识或许不能带给我们什么效果,也许根本就没有什么作用,但是当很多很多的知识混在一起就会由量变引发质变,曾经在人民日报上看到一句话,“任何不起眼的投入,乘以时间,都会变成可感叹而不可亵玩焉的鸿沟,任何比天大的差距,除以时间,都会沦为一滴一滴足以把青蛙煮烂的温水”。希望能合理利用自己的时间,未来更好的明天加油。在以后的时间里,大家共勉。

还有很多的谜题和其他的有意思的问题和答案,无聊的时候可以去看看。

来源:

字符谜题:http://blog.csdn.net/sunkun2013/article/details/16355749

智力题:http://mp.weixin.qq.com/s/aISHoPgdgPpIS-X8gpIBlA

目录
相关文章
|
8月前
|
存储 传感器 缓存
java变量与数据类型:整型、浮点型与字符类型
### Java数据类型全景表简介 本文详细介绍了Java的基本数据类型和引用数据类型,涵盖每种类型的存储空间、默认值、取值范围及使用场景。特别强调了`byte`、`int`、`long`、`float`、`double`等基本类型在不同应用场景中的选择与优化,如文件流处理、金融计算等。引用数据类型部分则解析了`String`、数组、类对象、接口和枚举的内存分配机制。
266 15
|
JavaScript Java Android开发
在cmd中运行javac编译java文件报错: 编码GBK的不可映射字符、 非法字符: \65279
在cmd中运行javac编译java文件报错: 编码GBK的不可映射字符、 非法字符: \65279
252 1
|
Java
Java——编码GBK的不可映射字符
Java——编码GBK的不可映射字符
315 1
|
Java Serverless
Java字符个数统计代码
Java字符个数统计代码
203 6
|
Java API 索引
Java中的字符串与字符操作详解
Java中的字符串与字符操作详解
|
存储 Java Apache
JAVA工具类匹配重复或者连续的字符和符号
JAVA工具类匹配重复或者连续的字符和符号
140 2
|
存储 缓存 Java
|
Java
Java集合类ArrayList应用 | 如何在字符串s1中删除有在字符串s2出现的字符?
这是一个关于Java编程面试题的摘要,题目要求从字符串s1中删除s2中存在的字符。解题思路包括使用ArrayList或StringBuilder实现。ArrayList实现时,遍历s1,如果字符不在s2中,则添加到ArrayList;StringBuilder实现有两种方法,一是新建StringBuilder并追加s1,然后遍历删除s2中的字符,二是直接在原地修改s1的StringBuilder对象。代码示例中展示了这些方法。
151 3