Oracle 专业认证 JavaSE8 编程测验(七)
十三、本地化
| 认证目标 |
|---|
| 使用 locale 对象读取和设置区域设置 |
| 创建并读取属性文件 |
| 为每个语言环境构建一个资源包,并在应用中加载一个资源包 |
今天,计算机和软件变得如此普遍,以至于它们在世界各地都被用于人类活动。对于任何与这些用户相关和有用的软件,它都需要本地化。我们使软件适应当地语言和习俗的过程称为本地化。
本地化就是让软件对来自不同文化的用户有用,换句话说,就是为来自不同国家或语言的用户定制软件。如何本地化一个软件应用?当您本地化软件应用时,应该注意两个重要的准则:
- 不要硬编码文本(比如给用户的消息,GUI 中的文本元素,等等。)并将它们分离到外部文件或专用类中。完成这一步后,在软件中添加对新语言环境的支持就变得轻而易举了。
- 考虑到本地化,处理特定于文化的方面,如日期、时间、货币和格式化数字。不要假定一个默认的区域设置,而是以这样一种方式设计,即获取和定制当前的区域设置。
在这一章中,你将学习如何本地化你的软件。本地化主要包括为不同的地区创建资源包,以及通过使软件适应不同的地区来使软件具有文化意识。在本章中,您还将学习如何创建和使用这些资源包。
现场
| 认证目标 | |
|---|---|
| 使用 locale 对象读取和设置区域设置 |
场所是“代表一个国家、语言或文化的地方”考虑一下加拿大-法国语言环境。加拿大的许多地方都讲法语,这可能是一个地区。换句话说,如果你想销售为说法语的加拿大人定制的软件,那么你需要使你的软件适合这个地区。在 Java 中,这个地区由代码fr_CA表示,其中fr是法语的缩写,CA是加拿大的缩写;我们将在本节的后面更详细地讨论区域设置的命名方案。
区域设置类
在 Java 中,java.util.Locale类为地区提供编程支持。表 13-1 列出了这个类中的重要方法。
表 13-1。
Important Methods in the Locale Class
| 方法 | 简短描述 |
|---|---|
static Locale[] getAvailableLocales() | 返回 JVM 支持的可用语言环境(即已安装的语言环境)的列表。 |
static Locale getDefault() | 返回 JVM 的默认语言环境。 |
static void setDefault(Locale newLocale) | 设置 JVM 的默认语言环境。 |
String getCountry() | 返回 locale 对象的国家代码。 |
String getDisplayCountry() | 返回区域设置对象的国家名称。 |
String getLanguage() | 返回区域设置对象的语言代码。 |
String getDisplayLanguage() | 返回区域设置对象的语言名称。 |
String getVariant() | 返回区域设置对象的变量代码。 |
String getDisplayVariant() | 返回区域设置对象的变体代码的名称。 |
String toString() | 返回一个由地区语言、国家、变量等代码组成的String。 |
清单 13-1 中的代码检测默认语言环境,并检查 JVM 中可用的语言环境。
Listing 13-1. AvailableLocales.java
import java.util.Locale;
import java.util.Arrays ;
class AvailableLocales {
public static void main(String []args) {
System.out.println("The default locale is: " + Locale.getDefault());
Locale [] locales = Locale.getAvailableLocales();
System.out.printf("No. of other available locales is: %d, and they are: %n",
locales.length);
Arrays.stream(locales).forEach(
locale -> System.out.printf("Locale code: %s and it stands for %s %n",
locale, locale.getDisplayName()));
}
}
它打印以下内容:
The default locale is: en_US
No. of other available locales is: 160, and they are:
Locale code: ms_MY and it stands for Malay (Malaysia)
Locale code: ar_QA and it stands for Arabic (Qatar)
Locale code: is_IS and it stands for Icelandic (Iceland)
Locale code: sr_RS_#Latn and it stands for Serbian (Latin,Serbia)
Locale code: no_NO_NY and it stands for Norwegian (Norway,Nynorsk)
Locale code: th_TH_TH_#u-nu-thai and it stands for Thai (Thailand,TH)
Locale code: fr_FR and it stands for French (France)
Locale code: tr and it stands for Turkish
Locale code: es_CO and it stands for Spanish (Colombia)
Locale code: en_PH and it stands for English (Philippines)
Locale code: et_EE and it stands for Estonian (Estonia)
Locale code: el_CY and it stands for Greek (Cyprus)
Locale code: hu and it stands for Hungarian
[...rest of the output elided...]
在分析输出之前,让我们看看程序中的方法。您使用Locale中的方法getDefault()来获取默认地区的代码。之后,在Locale类中使用getAvailableLocales()来获取 JVM 支持的语言环境列表。现在,为每个地区打印地区代码,并使用Locale的getDisplayName()方法打印描述性名称。
该程序将这个 JVM 的默认语言环境打印为en_US,这意味着默认语言环境是美国使用的英语。然后它打印出一个很长的可用地区列表;为了节省空间,我们只展示了输出的一小部分。从这个程序中,您知道有许多可用和受支持的语言环境,并且每个 JVM 都有一个默认的语言环境。
此输出中有四种不同的区域设置代码:
- “hu 和它代表匈牙利语”:只有一个代码,其中
hu代表匈牙利语 - “ms_MY 和它代表马来语(马来西亚)”:由下划线分隔的两个代码,其中
ms代表马来语,MY代表马来西亚 - “no_NO_NY,它代表挪威语(挪威,尼诺斯克)”:由下划线分隔的三个代码,如 no_NO_NY,其中
no代表挪威语,NO代表挪威,NY代表尼诺斯克语 - “th_th_TH_#u-nu-thai,它代表泰语(Thailand,TH)”:由下划线分隔的两个或三个初始代码,最后一个由
#或_#分隔,如在th_TH_TH_#u-nu-thai中,我们现在将讨论它。
以下是这些区域名称的编码方式:
language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
这种语言环境编码方案允许组合不同的变体来创建一个语言环境。对于“th_TH_TH_#u-nu-thai”的地区代码,
- 语言代码是
"th"(泰语),并且总是用小写字母书写 - 国家代码是
"TH"(泰国),并且总是用大写字母书写 - 变体名称为
"TH";这里它重复了国家代码,但也可以是任何字符串 - 脚本名称在这里是一个空字符串;如果给定,它将是一个四个字母的字符串,第一个字母大写,其余字母小写(例如,
Latn) - 扩展名跟在
#或_#字符之后(因为脚本是一个空字符串);在这个例子中是“u-nu-thai”
再举一个例子,考虑地区代码"sr_RS_#Latn",
- 语言代码为
"sr"(塞尔维亚语) - 国家代码是
"RS"(塞尔维亚) - 此处的变量名称为空
- 脚本名为
"Latn"(拉丁文),由四个字母组成,第一个字母大写,其余字母小写 - 这里的分机是空的
以英语为例,许多国家都讲英语。英语因使用该语言的国家而有所不同。我们都知道美式英语和英式英语不同,但是这样的版本很多。以下代码(清单 13-2 )从所有可用的语言环境中只过滤英语语言环境:
Listing 13-2. AvailableLocalesEnglish.java
import java.util.Locale;
import java.util.Arrays;
class AvailableLocalesEnglish {
public static void main(String []args) {
Arrays.stream(Locale.getAvailableLocales())
.filter(locale -> locale.getLanguage().equals("en"))
.forEach(locale ->
System.out.printf("Locale code: %s and it stands for %s %n",
locale, locale.getDisplayName()));
}
}
它会打印以下内容(输出和顺序可能会因您的机器而异):
Locale code: en_MT and it stands for English (Malta)
Locale code: en_GB and it stands for English (United Kingdom)
Locale code: en_CA and it stands for English (Canada)
Locale code: en_US and it stands for English (United States)
Locale code: en_ZA and it stands for English (South Africa)
Locale code: en and it stands for English
Locale code: en_SG and it stands for English (Singapore)
Locale code: en_IE and it stands for English (Ireland)
Locale code: en_IN and it stands for English (India)
Locale code: en_AU and it stands for English (Australia)
Locale code: en_NZ and it stands for English (New Zealand)
Locale code: en_PH and it stands for English (Philippines)
输出用英语表示不同的地区,只使用语言代码和国家代码。我们在Locale中使用了getLanguage()方法,它返回地区代码。还有哪些这样的方法?现在让我们探索一下Locale类中可用的方法。
获取区域设置详细信息和设置区域设置
Locale类中的 getter 方法如getLanguage()、getCountry()和getVariant()返回代码,而类似的方法getDisplayCountry()、getDisplayLanguage()和getDisplayVariant()返回名称。清单 13-3 展示了如何为地区Locale.CANADA_FRENCH使用这些方法。
Listing 13-3. LocaleDetails.java
import java.util.Locale;
public class LocaleDetails {
public static void main(String args[]) {
Locale.setDefault(Locale.CANADA_FRENCH);
Locale defaultLocale = Locale.getDefault();
System.out.printf("The default locale is %s %n", defaultLocale);
System.out.printf("The default language code is %s and the name is %s %n",
defaultLocale.getLanguage(), defaultLocale.getDisplayLanguage());
System.out.printf("The default country code is %s and the name is %s %n",
defaultLocale.getCountry(), defaultLocale.getDisplayCountry());
System.out.printf("The default variant code is %s and the name is %s %n",
defaultLocale.getVariant(), defaultLocale.getDisplayVariant());
}
}
它打印以下内容:
The default locale is fr_CA
The default language code is fr and the name is français
The default country code is CA and the name is Canada
The default variant code is and the name is
让我们来了解一下程序。setDefault()方法将一个Locale对象作为参数。在这个程序中,您使用下面的语句将默认语言环境设置为Locale.CANADA_FRENCH:
Locale.setDefault(Locale.CANADA_FRENCH);
Locale类有许多静态的Locale对象来表示常见的地区,这样你就不必实例化它们并直接在你的程序中使用它们。在这种情况下,Locale.CANADA_FRENCH是一个静态的Locale对象。
不使用这个静态的Locale对象,您可以选择实例化一个Locale对象。下面是通过创建新的加拿大(法语)区域设置对象来设置默认区域设置的另一种方法:
Locale.setDefault(new Locale("fr", "CA", ""));
Locale中的getDefault()方法返回 JVM 中的默认 locale 对象集。下一条语句使用方法获取与国家相关的信息。getCountry()和getDisplayCountry()方法的区别在于,前者返回国家代码(对我们来说可读性不强),后者返回国家名称,这是人类可读的。国家代码是两个或三个字母的代码(此代码来自国际标准:ISO 3166)。
getLanguage()和getDisplayLanguage()的行为类似于获取国家细节。语言代码由两个或三个字母组成(这个代码来自另一个国际标准:ISO 639)。
这个语言环境中没有变量,所以当您使用getVariant()和getDisplayVariant()方法时,不会打印任何东西。然而,对于其他一些地区,可能有不同的值,这些值将被打印出来。变量可以是任何额外的细节,如操作环境(如 MAC for Macintosh 机器)或公司名称(如 Sun 或 Oracle)。
除此之外,还有一些不太常用的方法,比如返回脚本代码和地区国家名称的getScript()和getDisplayCountry()。
不要调用
Locale的getDisplayCountry()方法,它不接受任何参数,你可以选择getDisplayCountry(Locale)的重载版本,它接受一个Locale对象作为参数。这将按照传递的区域设置打印国家的名称。例如,对于呼叫Locale.GERMANY.getDisplayCountry(),您将得到输出“德国”(这是德国人对他们国家的称呼);然而,对于调用Locale.GERMANY.getDisplayCountry(Locale.ENGLISH),您将得到输出“德国”(这是英国人对国名德国的称呼)
Different Ways to Create a Locale Object
有许多方法可以获得或创建一个Locale对象。我们在这里列出了四个选项,用于创建与其语言代码相对应的意大利语言环境的实例。
选项 1:使用Locale类的构造函数:Locale(String language, String country, String variant):
Locale locale1 = new Locale("it", "", "");
选项 2:使用Locale类中的forLanguageTag(String languageTag)方法:
Locale locale2 = Locale.forLanguageTag("it");
选项 3:通过实例化Locale.Builder构建一个Locale对象,然后从该对象调用setLanguageTag():
Locale locale3 = new Locale.Builder().setLanguageTag("it").build();
选项 4:在Locale类中为地区使用预定义的静态最终常量:
Locale locale4 = Locale.ITALIAN;
您可以根据需要选择创建Locale对象的方式。例如,Locale类只有几个针对地区的预定义常量。如果你想要一个预定义的Locale对象,你可以直接使用它,或者你必须检查使用哪个选项。
资源包
| 认证目标 | |
|---|---|
| 为每个语言环境构建一个资源包,并在应用中加载一个资源包 |
在上一节中,我们讨论了Locale类以及获取默认语言环境细节和可用语言环境列表的方法。如何使用这些地区信息来定制程序的行为?让我们举一个简单的问候别人的例子:在英语中,你说“你好”,但如果地区不同,你如何将这个问候改为,例如,“Ciao”,如果地区是意大利语(意大利)?
一个显而易见的解决方案是获取默认的区域设置,检查区域设置是否是意大利,并打印“Ciao”这是可行的,但是这种方法既不灵活也不可扩展。如何定制到其他地区,如沙特阿拉伯(阿拉伯语)或泰国(泰语)?您必须找到并替换所有特定于语言环境的字符串,以便为每个语言环境进行定制。如果您的应用由分布在一百万行代码中的数千个这样的字符串组成,并且需要支持许多地区,那么这项任务将是一场噩梦。
在 Java 中,资源包为如何定制应用以满足特定于地区的需求提供了一个解决方案。那么,什么是资源包呢?资源包是一组帮助定义一组键并将这些键映射到特定于地区的值的类或属性文件。
抽象类java.util.ResourceBundle提供了 Java 中资源束的抽象。它有两个派生类:java.util.PropertyResourceBundle和java.util.ListResourceBundle(见图 13-1 )。这两个派生类使用两种不同的机制为资源包提供支持:
图 13-1。
ResourceBundle and its two derived classes
PropertyResourceBundle类:这个具体的类以属性文件的形式提供了对多种语言环境的支持。对于每个区域设置,您可以在该区域设置的属性文件中指定键和值。对于给定的语言环境,如果使用ResourceBundle.getBundle()方法,相关的属性文件将被自动加载。当然,这里面没有魔法;创建属性文件必须遵循一定的命名约定,我们将在专门讨论属性文件的章节中讨论这一点。使用属性文件时,只能使用Strings作为键和值。ListResourceBundle类:为了增加对语言环境的支持,您可以扩展这个抽象类。在你的派生类中,你必须重写getContents()方法,它返回一个Object [][]。该数组必须有键和值的列表。按键必须是Strings。通常值也是Strings,但是值可以是任何东西:声音剪辑、视频剪辑、URL 或者图片。
让我们快速看一下ResourceBundle抽象类支持的方法。表 13-2 总结了这个类的重要方法。我们现在将讨论使用ResourceBundle的这两个派生类的本地化支持。
表 13-2。
Important Methods in the ResourceBundle Abstract Class
| 方法 | 简短描述 |
|---|---|
Object getObject(String key) | 返回映射到给定键的值。如果没有找到给定键的对象,抛出一个MissingResourceException。 |
static ResourceBundle getBundle(String baseName),``static final ResourceBundle getBundle(String baseName, Locale locale) | 返回给定的baseName、locale的ResourceBundle,如果没有找到匹配的资源包,control;抛出一个MissingResourceException。Control参数用于控制或获取资源包加载过程的信息 |
String getString(String key) | 返回映射到给定键的值;相当于将返回值从getObject()强制转换为String。如果没有找到给定键的对象,抛出一个MissingResourceException。如果返回的对象不是一个String,抛出ClassCastException。 |
使用 PropertyResourceBundle
| 认证目标 | |
|---|---|
| 创建并读取属性文件 |
如果您使用属性文件设计应用时考虑到了本地化,那么您可以在不更改任何代码的情况下为应用添加对新语言环境的支持!
现在我们来看一个使用资源文件的例子,你会明白的。让我们从一个非常简单的向用户输出“Hello”的程序开始。这个程序有三个属性文件资源包:
The default resource bundle that assumes the English (US) locale. A resource bundle for the Arabic locale. A resource bundle for the Italian locale.
如上所述,属性文件将字符串定义为文件中的键值对。下面是一个类路径的例子,它可以映射到机器中的一个实际路径:classpath=C:\Program Files\Java\jre8。属性文件通常包含许多这样的键值对,每个键值对位于单独的行中,如下所示:
classpath=C:\Program Files\Java\jre8
temp=C:\Windows\Temp
windir=C:\Windows
在本地化的情况下,使用属性文件将相同的键字符串映射到不同的值字符串。在程序中,您将引用键字符串,并通过加载与该地区相匹配的属性文件,从属性文件中获取键的相应值,以便在程序中使用。
这些属性文件的命名很重要(您很快就会明白为什么),下面是这些包的内容。为了使这个例子简单,在这些属性文件中只有一个键值对;在现实世界的程序中,每个属性文件中可能有几百甚至几千对。
D:\> type ResourceBundle.properties
Greeting=Hello
D:\> type ResourceBundle_ar.properties
Greeting=As-Salamu Alaykum
D:\> type ResourceBundle_it.properties
Greeting=Ciao
如您所见,默认的包名为ResourceBundle.properties。阿拉伯语的资源包被命名为ResourceBundle_ar.properties。注意后缀“_ar”,表示阿拉伯语是本地语言。类似地,意大利语的资源包被命名为ResourceBundle_it.properties,它使用"_it"后缀来表示意大利语是这个属性文件的关联语言。清单 13-4 利用了这些资源包。
Listing 13-4. LocalizedHello.java
import java.util.Locale;
import java.util.ResourceBundle;
public class LocalizedHello {
public static void main(String args[]) {
Locale currentLocale = Locale.getDefault();
ResourceBundle resBundle =
ResourceBundle.getBundle("ResourceBundle", currentLocale);
System.out.printf(resBundle.getString("Greeting"));
}
}
图 13-2。
Getting relevant strings from ResourceBundles based on the locale
有两个选项可以按所需方式运行该程序:
- 选项 I:通过调用
setDefault()方法来更改程序中的默认区域设置:Locale.setDefault(Locale.ITALY);不推荐使用该选项,因为它需要更改程序来设置区域设置。 - 选项 II:从命令行调用 JVM 时更改默认的语言环境(如果您从 ide 调用 JVM,请在 IDE 设置中为 JVM 提供命令行参数):
D:\> java -Duser.language=it -Duser.region=IT LocalizedHello
让我们通过用选项 II(调用 JVM 时向命令行传递参数)设置语言环境来尝试这个程序。
D:\> java LocalizedHello
Hello
D:\> java -Duser.language=it LocalizedHello
Ciao
D:\> java -Duser.language=ar LocalizedHello
As-Salamu Alaykum
正如您所看到的,根据您显式设置的地区(本例中是意大利语或阿拉伯语),或者默认地区(本例中是美国英语),相应的属性文件被加载,消息字符串被解析。
如果您忘记创建属性文件或者它们不在路径中,您将得到一个
MissingResourceException。
在程序中,首先在语句中获取当前的区域设置。
Locale currentLocale = Locale.getDefault();
之后,加载以名称ResourceBundle开始的资源包,并传递加载资源包的区域设置。
ResourceBundle resBundle = ResourceBundle.getBundle("ResourceBundle", currentLocale);
最后,从资源包中,查找关键字“Greeting ”,并根据加载的资源包使用该关键字的值。
System.out.printf(resBundle.getString("Greeting"));
使用 ListResourceBundle
可以使用ListResourceBundle通过扩展来添加对新语言环境的支持。在扩展ListResourceBundle的时候,你需要覆盖抽象方法getContents();,这个方法的签名是:
protected Object[][] getContents();
注意键是Strings,但是值可以是任何类型,因此数组类型是Object;此外,该方法返回键和值对的列表。结果,getContents()方法返回一个二维数组Objects。
您通过扩展
ListResourceBundle类来创建资源包,而使用PropertyResourceBundle,您将资源包创建为属性文件。此外,当扩展ListResourceBundle时,可以将任何类型的对象作为值,而属性文件中的值只能是字符串。
清单 13-5 展示了一个扩展ListResourceBundle的例子,它返回特定地区最卖座的电影。它定义了名为ResBundle的资源包。因为类名没有任何后缀(比如"_it"或者"_en_US",所以它是资源包的默认实现。在为任何地区寻找匹配的ResBundle时,如果找不到匹配,将使用这个默认实现。
Listing 13-5. ResBundle.java
import java.util.ListResourceBundle;
// default US English version
public class ResBundle extends ListResourceBundle {
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
{ "MovieName", "Avatar" },
{ "GrossRevenue", (Long) 2782275172L }, // in US dollars
{ "Year", (Integer)2009 }
};
}
现在,让我们为意大利地区定义一个ResBundle。您给这个类加上后缀"_it_IT"。语言代码"it"代表意大利语,国家代码"IT"代表意大利(列表 13-6 )。
Listing 13-6. ResBundle_it_IT.java
import java.util.ListResourceBundle;
// Italian version
public class ResBundle_it_IT extends ListResourceBundle {
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
{ "MovieName", "Che Bella Giornata" },
{ "GrossRevenue", (Long) 43000000L }, // in euros
{ "Year", (Integer)2011 }
};
}
正如您所看到的,除了映射到键的值之外,ResBundle和ResBundle_it_IT的实现是相似的。现在,您如何知道您的资源包是否在工作呢?清单 13-7 加载默认和意大利语言环境的ResBundle。
Listing 13-7. LocalizedBoxOfficeHits.java
import java.util.ResourceBundle;
import java.util.Locale;
public class LocalizedBoxOfficeHits {
public void printMovieDetails(ResourceBundle resBundle) {
String movieName = resBundle.getString("MovieName");
Long revenue = (Long)(resBundle.getObject("GrossRevenue"));
Integer year = (Integer) resBundle.getObject("Year");
System.out.println("Movie " + movieName + "(" + year + ")" + " grossed "
+ revenue );
}
public static void main(String args[]) {
LocalizedBoxOfficeHits localizedHits = new LocalizedBoxOfficeHits();
// print the largest box-office hit movie for default (US) locale
Locale locale = Locale.getDefault();
localizedHits.printMovieDetails(ResourceBundle.getBundle("ResBundle", locale));
// print the largest box-office hit movie for Italian locale
locale = new Locale("it", "IT", "");
localizedHits.printMovieDetails(ResourceBundle.getBundle("ResBundle", locale));
}
}
它打印以下内容:
Movie Avatar (2009) grossed 2782275172
Movie Che Bella Giornata (2011) grossed 43000000
它成功加载了默认和意大利资源包。但是,这个输出存在一些问题。值 2782275172 是美元值,值 43000000 是欧元值。而且数字打印出来没有逗号,很难搞清楚这些数字的意义。可以本地化这些货币值的格式。但是处理数字格式、十进制格式和地区间的货币差异并不包含在 OCPJP 8 考试中,所以我们在本书中不做进一步的讨论。
现在,考虑该程序中的以下语句:
Long revenue = (Long)(resBundle.getObject("GrossRevenue"));
该语句返回映射到资源包中名为GrossRevenue的键的值。你已经在类ResBundle和ResBundle_it_IT中将它定义为一个Long对象——所以它工作了。例如,如果您错误地将类型转换为Integer,您将得到一个ClassCastException,如下所示:
Integer revenue = (Integer)(resBundle.getObject("GrossRevenue"));
// This code change will result in throwing this exception:
// Exception in thread "main" java.lang.ClassCastException:
// java.lang.Long cannot be cast to java.lang.Integer
这里是另一种情况:如果您错误地键入了GrossRevenu而不是GrossRevenue作为键名,程序将会崩溃并出现这个异常,如下所示:
Long revenue = (Long)(resBundle.getObject("GrossRevenu"));
// This code will crash with this exception:
// Exception in the thread "main" java.util.MissingResourceException:
// Can't find resources for bundle ResBundle, key GrossRevenu
为了从资源包中获取对象,在提供 keyname 时需要小心:keyname 是区分大小写的,键名应该完全匹配——否则会得到 MissingResourceException。
加载资源包
| 认证目标 | |
|---|---|
| 为每个语言环境构建一个资源包,并在应用中加载一个资源包 |
您已经在使用ResourceBundle或它的两个派生类编写的程序中加载了资源包。从考试的角度来看,您需要彻底理解这个加载过程,所以我们将在本节中更详细地讨论它。
对于从ListResourceBundles扩展的类,寻找匹配资源包的过程与为PropertyResourceBundles定义的属性文件相同。
对于实现为从
ListResourceBundles扩展的类的资源包,Java 使用反射机制来查找和加载类。您需要确保该类是公共的,以便反射机制可以找到该类。
资源包的命名约定
Java 强制执行一个预定义的命名约定来创建资源包。Java 库只通过属性包的名称加载相关的语言环境。因此,在创建用于本地化 Java 应用的属性包时,理解并遵循这个命名约定是很重要的。
您已经看到了语言环境名称是如何编码的。理解这种语言环境名称编码对于命名资源包非常重要,因为它使用相同的编码方案。完全限定的资源包具有以下形式:
packagequalifier.bundlename + "_" + language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
以下是该完全限定名称中元素的描述:
packagequalifier:提供资源包的包(或子包)的名称。bundlename:您将在程序中引用和加载的资源包的名称。language:两个字母的缩写,通常以小写形式表示该地区的语言(在极少数情况下,也可以是三个字母)。country:两个字母的缩写,通常以大写形式表示该地区的国家(在极少数情况下,也可以是三个字母)。variant:当您需要一个以上的语言和国家组合的地区时,一个任意的变量列表(小写或大写)来区分地区。
我们已经省略了对脚本和扩展的描述,因为它们很少被使用。
例如,考虑这个完全限定名:
localization.examples.AppBundle_ en_US_Oracle_exam
在本例中,localization.examples是包,AppBundle是资源包的名称,en是语言(代表英语),US是国家,Oracle_exam是变体。
地区语言和国家的两个(有时三个)字母缩写是预定义的,因为它们是基于国际标准的。我们不提供详细的列表,也没有必要在考试中知道或记住所有的列表。您可以查看Locale类的文档来理解这一点。
在 OCPJP 八级考试中,你不需要记住用于命名资源包的语言代码或国家代码。但是,您应该记住命名约定,并认识到完全限定的资源包名称的组成部分。
假设一个包名可能有多个资源包,那么确定要加载的资源包的搜索顺序是什么?为了清楚起见,我们将该序列表示为一系列步骤。搜索从步骤 1 开始。如果在任何步骤中搜索发现匹配,则加载资源包。否则,搜索进行到下一步(见图 13-3 )。
图 13-3。
Seach sequence for ResourceBundles
搜索从给定的区域设置细节开始,如果没有找到,则继续检查默认区域设置,如下所示:
BundleName + "_" + language + "_" + country + "_" + variant
BundleName + "_" + language + "_" + country
BundleName + "_" + language
BundleName + "_" + defaultLanguage + "_" + defaultCountry
BundleName + "_" + defaultLanguage
考虑一个例子,看看如何找到匹配的资源包,你就清楚了。假设您在搜索路径中有以下五个条目,并且您的默认区域设置是美国英语。
ResourceBundle.properties -- Global bundle
ResourceBundle_ar.properties -- Arabic language bundle
ResourceBundle_en.properties -- English bundle (assuming en_US is the default locale)
ResourceBundle_it.properties -- Italian language bundle
ResourceBundle_it_IT_Rome.properties -- Italian (Italy, Rome) bundle
getBundle()方法将一个ResourceBundle.Control对象作为附加参数。通过扩展这个ResourceBundle.Control类并将该扩展类的实例传递给getBundle()方法,您可以改变默认的资源包搜索过程或者读取非标准的资源包格式(比如 XML 文件)。
我们如何才能找出 Java 正在搜索的语言环境的顺序呢?为此,让我们扩展ResourceBundle.Control类并覆盖getCandidateLocales()方法:这是为了以编程方式访问和打印候选地区列表,并最终显示匹配的地区。请注意,“候选语言环境”是指 Java 在搜索过程中考虑的语言环境。假设名为ResourceBundle_it_IT_Rome.properties和ResourceBundle_en.properties的属性文件可用。该程序在清单 13-8 中给出。
Listing 13-8. CandidateLocales.java
import java.util.ResourceBundle;
import java.util.List;
import java.util.Locale;
// Extend ResourceBundle.Control and override getCandidateLocales method
// to get the list of candidate locales that Java searches for
class TalkativeResourceBundleControl extends ResourceBundle.Control {
// override the default getCandidateLocales method to print
// the candidate locales first
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
List<Locale> candidateLocales = super.getCandidateLocales(baseName, locale);
System.out.printf("Candidate locales for base bundle name %s and locale %s %n",
baseName, locale.getDisplayName());
candidateLocales.forEach(System.out::println);
return candidateLocales;
}
}
// Use a helper method loadResourceBundle to load a bundle given the bundle name and locale
class CandidateLocales {
public static void loadResourceBundle(String resourceBundleName, Locale locale) {
// Pass an instance of TalkativeResourceBundleControl
// to print candidate locales
ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName,
locale, new TalkativeResourceBundleControl());
String rbLocaleName = resourceBundle.getLocale().toString();
// if the resource bundle locale name is empty,
// it means default property file
if(rbLocaleName.equals("")) {
System.out.println("Loaded the default property file with name: "
+ resourceBundleName);
} else {
System.out.println("Loaded the resource bundle for the locale: "
+ resourceBundleName + "." + rbLocaleName);
}
}
public static void main(String[] args) {
// trace how ResourceBundle_it_IT_Rome.properties is resolved
loadResourceBundle("ResourceBundle", new Locale("it", "IT", "Rome"));
}
}
它打印以下内容:
Candidate locales for base bundle name ResourceBundle and locale Italian (Italy, Rome)
it_IT_Rome
it_IT
it
Loaded the resource bundle for the locale: ResourceBundle.it_IT_Rome
现在,在尝试其他语言环境之前,考虑一下程序是如何工作的。为了跟踪 Java 如何解析最终加载的资源包,您需要获得候选语言环境的列表。使用ResourceBundle.getBundle()方法,您可以传递一个额外的参数,它是ResourceBundle.Control类的一个实例。出于这个原因,您定义了TalkativeResourceBundleControl类。
TalkativeResourceBundleControl类扩展了ResourceBundle.Control类并覆盖了getCandidateLocales()方法。这个getCandidateLocales()方法返回一个List<Locale>实例,其中包含给定地区的候选地区列表。您调用super.getCandidateLocales()并遍历产生的List<Locale>对象来打印候选语言环境,以便稍后可以检查输出。从这个被覆盖的getCandidateLocales()方法中,您只需返回这个List<Locale>对象。因此,TalkativeResourceBundleControl的行为与ResourceBundle.Control相同,除了TalkativeResourceBundleControl中被覆盖的getCandidateLocales()打印候选语言环境。
CandidateLocales类利用了TalkativeResourceBundleControl。它有一个名为loadResourceBundle()的助手方法,该方法将资源包名称和地区名称作为参数。这个方法只是将这些参数值传递给ResourceBundle.getBundle()方法;此外,它实例化了TalkativeResourceBundleControl,并将该对象作为第三个参数传递给该方法。getBundle()方法返回一个ResourceBundle对象。如果ResourceBundle.getLocale()名称的区域设置为空,则意味着 Java 已经加载了全局资源包。(请记住,该包名称的全局资源包没有任何相关的区域设置细节。)如果语言环境的名称不为空,则意味着 Java 已经解析到该特定的语言环境。
现在,考虑一下main()方法中的代码。它为地区it_IT_Rome调用loadResourceBundle()。有三个候选语言环境,其中它正确地加载了与语言环境it_IT_Rome匹配的属性文件。所以你知道它正确地加载了属性文件ResourceBundle_it_IT_Rome.properties。
为了继续这个实验,让我们将清单 13-8 的main()方法中的代码改为如下代码:
loadResourceBundle("ResourceBundle", new Locale("fr", "CA", ""));
现在,该程序打印以下内容:
Candidate locales for base bundle name ResourceBundle and locale French (Canada)
fr_CA
fr
Candidate locales for base bundle name ResourceBundle and locale English (United States)
en_US
en
Loaded the resource bundle for the locale: ResourceBundle.en
为什么程序会打印出上面的输出?注意,在属性文件列表中没有对应于fr_CA地区的属性文件。因此,搜索将继续检查默认语言环境的属性文件。在这种情况下,默认的地区是en_US,并且有一个属性文件用于en(英语)地区。因此,从候选语言环境中,Java 决定正确地加载属性文件ResourceBundle_en.properties。
这是最后一个例子。用以下语句替换main()方法中的代码:
loadResourceBundle("ResBundl", Locale.getDefault());
该程序打印以下内容:
Candidate locales for base bundle name ResBundl and locale English (United States)
en_US
en
The exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name ResBundl, locale en_US
[... thrown stack trace elided ...]
您没有任何名为ResBundl的资源包,并且您已经给出了默认的语言环境(在本例中为en_US)。Java 搜索这个地区的包,您知道您没有提供任何名为ResBundl的包。所以,程序在抛出一个MissingResourceException后崩溃。
摘要
让我们简要回顾一下本章中每个认证目标的要点。请在参加考试之前阅读它。
使用 locale 对象读取和设置区域设置
- 区域设置代表一种语言、文化或国家;Java 中的
Locale类为这个概念提供了一个抽象。 - 每个区域设置可以有三个条目:语言、国家和变体。您可以使用适用于语言和国家的标准代码来构成区域设置标签。变体没有标准标签;您可以根据需要提供不同的字符串。
Locale类中的 getter 方法——如getLanguage()、getCountry(),、getVariant()——返回代码;而getDisplayCountry()、getDisplayLanguage()、getDisplayVariant()的类似方法返回名字。Locale中的getDefault()方法返回 JVM 中的默认区域设置。您可以使用setDefault()方法将这个默认语言环境更改为另一个语言环境。- 有许多方法可以创建或获取对应于一个地区的
Locale对象:- 使用
Locale类的构造函数。 - 使用
Locale类中的forLanguageTag(String languageTag)方法。 - 通过实例化
Locale.Builder构建一个Locale对象,然后从该对象调用setLanguageTag()。 - 在
Locale类中为区域设置使用预定义的静态 final 常量。
- 使用
创建并读取属性文件
- 资源包是一组帮助定义一组键并将这些键映射到特定于地区的值的类或属性文件。
- 类
ResourceBundle有两个派生类:PropertyResourceBundle和ListResourceBundle。您可以使用ResourceBundle.getBundle()来获取给定地区的包。 The PropertyResourceBundle类以属性文件的形式提供对多种语言环境的支持。对于每个区域设置,您可以在该区域设置的属性文件中指定键和值。您只能使用String作为键和值。- 要添加对新语言环境的支持,您可以扩展
ListResourceBundle类。在这个派生类中,你必须重写the Object [][] getContents()方法。返回的数组必须包含键和值的列表。键必须是字符串,值可以是任何对象。 - 当将键字符串传递给
getObject()方法以获取资源包中的匹配值时,确保传递的键和资源包中的键完全匹配(keyname 区分大小写)。如果不匹配,你会得到一个MissingResourceException。 - 完全限定的资源包名称的命名约定是
packagequalifier.bundlename + "_" + language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions。
为每个语言环境构建一个资源包,并在应用中加载一个资源包
- 对于从
ListResourceBundles扩展的类,寻找匹配资源包的过程与为PropertyResourceBundles定义的属性文件相同。 - 下面是查找匹配资源包的搜索序列。搜索从步骤 1 开始。如果在任何步骤中搜索发现匹配,则加载资源包。否则,搜索进行到下一步。
- 步骤 1:搜索从寻找与资源束完全匹配的全名开始。
- 步骤 2:删除最后一个组件(由 _ 分隔的部分),并使用得到的较短名称重复搜索。重复这个过程,直到剩下最后一个区域设置修饰符。
- 步骤 3:使用默认地区的包的全名继续搜索。
- 步骤 4:只使用包的名称搜索资源包。
- 第五步:搜索失败,抛出一个
MissingBundleException。
getBundle()方法将一个ResourceBundle.Control对象作为附加参数。通过扩展这个ResourceBundle.Control类并传递那个对象,您可以控制或定制资源包搜索和加载过程。
Question TimeWhich one of the following statements makes use of a factory method? Locale locale1 = new Locale("it", "", ""); NumberFormat.getInstance(Locale.GERMANY); Locale locale3 = new Locale.Builder().setLanguageTag("it").build(); Date today = new Date(); Locale locale4 = Locale.ITALIAN; Consider the following program and choose the correct option: import java.util.Locale; class Test { public static void main(String []args) { Locale locale1 = new Locale("en"); //#1 Locale locale2 = new Locale("en", "in"); //#2 Locale locale3 = new Locale("th", "TH", "TH"); //#3 Locale locale4 = new Locale(locale3); //#4 System.out.println(locale1 + " " + locale2 + " " + locale3 + " " + locale4); } } This program will print the following: en en_IN th_TH_TH_#u-nu-thai th_TH_TH_#u-nu-thai. This program will print the following: en en_IN th_TH_TH_#u-nu-thai (followed by a runtime exception). This program results in a compiler error at statement #1. This program results in a compiler error at statement #2. This program results in a compiler error at statement #3. This program results in a compiler error at statement #4. Choose the best option based on this program: import java.util. Locale; class LocaleTest { public static void main(String []args) { Locale locale = new Locale("navi", "pandora"); //#1 System.out.println(locale); } } The program results in a compiler error at statement #1. The program results in a runtime exception of NoSuchLocaleException. The program results in a runtime exception of MissingResourceException. The program results in a runtime exception of IllegalArgumentException. The program prints the following: navi_PANDORA. For localization, resource bundle property files are created that consist of key-value pairs. Which one of the following is a valid key value pair as provided in a resource bundle property file for some strings mapped to German language? A. <pair> <key>from</key> <value>von</value> </pair> <pair> <key>subject</key> <value> betreff </value> </pair> B. from=von subject=betreff C. key=from; value=von key=subject; value=betreff D. pair<from,von> pair<subject,betreff> Assume that you’ve the following resource bundles in your classpath: ResourceBundle.properties ResourceBundle_ar.properties ResourceBundle_en.properties ResourceBundle_it.properties ResourceBundle_it_IT_Rome.properties Also assume that the default locale is English (US), where the language code is en and country code is US. Which one of these five bundles will be loaded for the call loadResourceBundle("ResourceBundle", new Locale("fr", "CA", ""));? ResourceBundle.properties ResourceBundle_ar.properties ResourceBundle_en.properties ResourceBundle_it.properties ResourceBundle_it_IT_Rome.properties Which of the following is a correct override for extending the ListResourceBundle class? A. public HashMap<String, String> getContents() { Map<String, String> contents = new HashMap<>(); contents.add("MovieName", "Avatar"); return contents; } B. public Object[] getContents() { return new Object[] { { "MovieName" } , { "Avatar" } }; } C. public Object[][] getContents() { return new Object[][] { { "MovieName", "Avatar" } }; } D. public String[] getKeysAndValues() { return new String[] { { "MovieName" } , { "Avatar" } }; } E. public String[] getProperties() { return new String[] { { "MovieName" }, { "Avatar" } }; }
答案:
B. NumberFormat.getInstance(Locale.GERMANY); A factory method creates an instance and returns back. Using a constructor directly to create an object is not related to a factory method, so A) and D) are not correct. C) builds a locale and is an example for using the Builder pattern. E) merely accesses the predefined Locale object; so it’s not a method. F. This program results in a compiler error at #4. The Locale class supports three constructors that are used in statements #1, #2, and #3; however, there is no constructor in the Locale class that takes another Locale object as argument, so the compiler gives an error for statement #4. E. The program prints the following: navi_PANDORA. To create a Locale object using the constructor Locale(String language, String country), any String values can be passed. Just attempting to create a Locale object will not result in throwing exceptions other than a NullPointerException, which could be raised for passing null Strings. The toString() method of Locale class returns a string representation of the Locale object consisting of language, country, variant, etc.) B. from=von subject=betreff In the resource bundle property files, the key values are separated using the = symbol, with each line in the resource file separated by a newline character. C. ResourceBundle_en.properties Java looks for candidate locales for a base bundle namedResourceBundle and locale French (Canada), and checks for the presence of the following property files: ResourceBundle_fr_CA.properties ResourceBundle_fr.properties Since both of them are not there, Java searches for candidate locales for the base bundle named ResourceBundle and a default locale (English - United States): ResourceBundle_en_US.properties ResourceBundle_en.properties Java finds that there is a matching resource bundle, ResourceBundle_en.properties. Hence it loads this resource bundle. C. public Object[][] getContents() { return new Object[][] { { "MovieName", "Avatar" } }; } The return type of the getContents() method is Object[][]. Further, the method should return a new object of type Object [][] from the method body. Hence, option C) is the correct answer.
十四、模拟考试
参加 OCPJP 八级考试的前景在你心中引发了许多问题。
- "考试中会问哪些类型的问题?"
- "问题的形式是什么?"
- “题目有多难?”
- “我如何知道我是否准备好参加考试?”
本章提供了一个模拟考试来帮助回答这些问题。用这个模拟考试作为一个智力测试,来衡量你为通过 OCPJP 八级考试做了多少准备。
这次模拟考试中的问题非常接近你在 OCPJP 8 考试中会遇到的实际问题。例如,你会在实际的 OCPJP 八级考试中发现这些方面:问题将假设必要的重要陈述被包括在内;大多数问题将只包含相关的代码段(而不是完整的程序);而且问题会随机出现(而且不是按照考试大纲给的考试题目顺序)。在这次模拟考试中,我们采用了类似的方法,使这次模拟考试非常接近真实的 OCPJP 八级考试中的问题格式。
在开始之前,请从考试结束时给出的答题纸上打印一份答案。通过模拟真实的考试条件,就像参加真正的 OCPJP 八级考试一样参加这次考试。找一个安静的地方,在那里你可以不受干扰或分心地参加模拟考试。标记你的开始和结束时间,如果超过考试时间限制(2.5 小时)就停止。遵守闭卷规则:在这次模拟考试中,不要查阅答案或任何其他印刷、人力或网络资源。完成考试后再检查答案。在 85 个问题中,您需要正确回答至少 55 个问题才能通过本次考试(及格分数为 65%)。
祝你好运!
Time: 2 hours 30 minutesNo. of questions: 85What will be the result of executing this code segment ? Stream.of("ace ", "jack ", "queen ", "king ", "joker ") .mapToInt(card -> card.length()) .filter(len -> len > 3) .peek(System.out::print) .limit(2); This code segment prints: jack queen king joker This code segment prints: jack queen This code segment prints: king joker This code segment does not print anything on the console Consider the following snippet: int ch = 0; try (FileReader inputFile = new FileReader(file)) { // #1 System.out.print( (char)ch ); } } Which one of the following statements can be replaced with statement #1 so that the contents of the file are correctly printed on the console and the program terminates. while( (ch = inputFile.read()) != null) { while( (ch = inputFile.read()) != -1) { while( (ch = inputFile.read()) != 0) { while( (ch = inputFile.read()) != EOF) { What will be the output of the following program? class Base { public Base() { System.out.println("Base"); } } class Derived extends Base { public Derived() { System.out.println("Derived"); } } class DeriDerived extends Derived { public DeriDerived() { System.out.println("DeriDerived"); } } class Test { public static void main(String []args) { Derived b = new DeriDerived(); } } Base Derived DeriDerived Derived DeriDerived DeriDerived Derived Base DeriDerived Derived DeriDerived Given this code segment: final CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("Let's play")); // LINE_ONE Runnable r = () -> { // LINE_TWO System.out.println("Awaiting"); try { barrier.await(); } catch(Exception e) { /* ignore */ } }; Thread t1 = new Thread(r); Thread t2 = new Thread(r); Thread t3 = new Thread(r); t1.start(); t2.start(); t3.start(); Choose the correct option based on this code segment. This code segment results in a compiler error in line marked with the comment LINE_ONE This code segment results in a compiler error in line marked with the comment LINE_TWO This code prints: Let's play This code prints: Awaiting Awaiting Awaiting Let's play This code segment does not print anything on the console Given this class definition : class Point { private int x = 0, y; public Point(int x, int y) { this.x = x; this.y = y; } // DEFAULT_CTOR } Which one of the following definitions of the Point constructor can be replaced without compiler errors in place of the comment DEFAULT_CTOR ? a) public Point() { this(0, 0); super(); } b) public Point() { super(); this(0, 0); } c) private Point() { this(0, 0); } d) public Point() { this(); } e) public Point() { this(x, 0); } Consider the following program: class Base { public Base() { System.out.print("Base "); } public Base(String s) { System.out.print("Base: " + s); } } class Derived extends Base { public Derived(String s) { super(); // Stmt-1 super(s); // Stmt-2 System.out.print("Derived "); } } class Test { public static void main(String []args) { Base a = new Derived("Hello "); } } Select three correct options from the following list: Removing only Stmt-1 will make the program compilable and it will print the following: Base Derived Removing only Stmt-1 will make the program compilable and it will print the following: Base: Hello Derived Removing only Stmt-2 will make the program compilable and it will print the following: Base Derived Removing both Stmt-1 and Stmt-2 will make the program compilable and it will print the following: Base Derived Removing both Stmt-1 and Stmt-2 will make the program compilable and it will print the following: Base: Hello Derived Consider the following program and choose the right option from the given list: class Base { public void test() { protected int a = 10; // #1 } } class Test extends Base { // #2 public static void main(String[] args) { System.out.printf(null); // #3 } } The compiler will report an error at statement marked with the comment #1 The compiler will report an error at statement marked with the comment #2 The compiler will report errors at statement marked with the comment #3 The program will compile without any error Given this code segment: LocalDate joiningDate = LocalDate.of(2014, Month.SEPTEMBER, 20); LocalDate now = LocalDate.of(2015, Month.OCTOBER, 20); // GET_YEARS System.out.println(years); Which one of the following statements when replaced by the comment GET_ YEARS will print 1 on the console? Period years = Period.between(joiningDate, now).getYears(); Duration years = Period.between(joiningDate, now).getYears(); int years = Period.between(joiningDate, now).getYears(); Instant years = Period.between(joiningDate, now).getYears(); Consider the following program: class Outer { class Inner { public void print() { System.out.println("Inner: print"); } } } class Test { public static void main(String []args) { // Stmt#1 inner.print(); } } Which one of the following statements will you replace with // Stmt#1 to make the program compile and run successfully to print “Inner: print” in console? Outer.Inner inner = new Outer.Inner(); Inner inner = new Outer.Inner(); Outer.Inner inner = new Outer().Inner(); Outer.Inner inner = new Outer().new Inner(); Consider the following program: public class Outer { private int mem = 10; class Inner { private int imem = new Outer().mem; // ACCESS1 } public static void main(String []s) { System.out.println(new Outer().new Inner().imem); // ACCESS2 } } Which one of the following options is correct? When compiled, this program will result in a compiler error in line marked with comment ACCESS1 When compiled, this program will result in a compiler error in line marked with comment ACCESS2 When executed, this program prints 10 When executed, this program prints 0 Consider the following program: interface EnumBase { } enum AnEnum implements EnumBase { // IMPLEMENTS_INTERFACE ONLY_MEM; } class EnumCheck { public static void main(String []args) { if(AnEnum.ONLY_MEM instanceof AnEnum) { System.out.println("yes, instance of AnEnum"); } if(AnEnum.ONLY_MEM instanceof EnumBase) { System.out.println("yes, instance of EnumBase"); } if(AnEnum.ONLY_MEM instanceof Enum) { // THIRD_CHECK System.out.println("yes, instance of Enum"); } } } Which one of the following options is correct? This program results in a compiler error in the line marked with comment IMPLEMENTS_INTERFACE This program results in a compiler in the line marked with comment THIRD_CHECK When executed, this program prints the following: yes, instance of AnEnum When executed, this program prints the following: yes, instance of AnEnum yes, instance of EnumBase When executed, this program prints the following: yes, instance of AnEnum yes, instance of EnumBase yes, instance of Enum Which of the following statements are true with respect to enums? (Select all that apply.) An enum can have private constructor An enum can have public constructor An enum can have public methods and fields An enum can implement an interface An enum can extend a class Choose the correct option based on this program: class base1 { protected int var; } interface base2 { int var = 0; // #1 } class Test extends base1 implements base2 { // #2 public static void main(String args[]) { System.out.println("var:" + var); // #3 } } The program will report a compilation error at statement marked with the comment #1 The program will report a compilation error at statement marked with the comment #2 The program will report a compilation error at statement marked with the comment #3 The program will compile without any errors Consider the following program: class WildCard { interface BI {} interface DI extends BI {} interface DDI extends DI {} static class C<T> {} static void foo(C<? super DI> arg) {} public static void main(String []args) { foo(new C<BI>()); // ONE foo(new C<DI>()); // TWO foo(new C<DDI>()); // THREE foo(new C()); // FOUR } } Which of the following options are correct? Line marked with comment ONE will result in a compiler error Line marked with comment TWO will result in a compiler error Line marked with comment THREE will result in a compiler error Line marked with comment FOUR will result in a compiler error Consider the following definitions: interface BI {} interface DI extends BI {} The following options provide definitions of a template class X. Which one of the options specifies class X with a type parameter whose upper bound declares DI to be the super type from which all type arguments must be derived? class X <T super DI> { } class X <T implements DI> { } class X <T extends DI> { } class X <T extends ? & DI> { } In the context of Singleton pattern, which one of the following statements is true? A Singleton class must not have any static members A Singleton class has a public constructor A Factory class may use Singleton pattern All methods of the Singleton class must be private Consider the following program: class ClassA {} interface InterfaceB {} class ClassC {} class Test extends ClassA implements InterfaceB { String msg; ClassC classC; } Which one of the following statements is true? Class Test is related with ClassA with a HAS-A relationship. Class Test is related to ClassC with a composition relationship. Class Test is related with String with an IS-A relationship. Class ClassA is related with InterfaceB with an IS-A relationship. Choose the correct option based on the following code segment: Comparator<String> comparer = (country1, country2) -> country2.compareTo(country2); // COMPARE_TO String[] brics = {"Brazil", "Russia", "India", "China"}; Arrays.sort(brics, null); Arrays.stream(brics).forEach(country -> System.out.print(country + " ")); The program results in a compiler error in the line marked with the comment COMPARE_TO The program prints the following: Brazil Russia India China The program prints the following: Brazil China India Russia The program prints the following: Russia India China Brazil The program throws the exception InvalidComparatorException The program throws the exception InvalidCompareException The program throws the exception NullPointerException Which one of the following class definitions will compile without any errors? a) class P<T> { static T s_mem; } b) class Q<T> { T mem; public Q(T arg) { mem = arg; } } c) class R<T> { T mem; public R() { mem = new T(); } } d) class S<T> { T []arr; public S() { arr = new T[10]; } } In a class that extends ListResourceBundle , which one of the following method definitions correctly overrides the getContents() method of the base class? a) public String[][] getContents() { return new Object[][] { { "1", "Uno" }, { "2", "Duo" }, { "3", "Trie" }}; } b) public Object[][] getContents() { return new Object[][] { { "1", "Uno" }, { "2", "Duo" }, { "3", "Trie" }}; } c) private List<String> getContents() { return new ArrayList (Arrays.AsList({ { "1", "Uno" }, { "2", "Duo" }, { "3", "Trie" }}); } d) protected Object[] getContents(){ return new String[] { "Uno", "Duo", "Trie" }; } Which one of the following interfaces declares a single abstract method named iterator()? (Note: Implementing this interface allows an object to be the target of the for-each statement.) Iterable<T> Iterator<T> Enumeration<E> ForEach<T> Choose the correct option based on this program: import java.util.stream.Stream; public class Reduce { public static void main(String []args) { Stream<String> words = Stream.of("one", "two", "three"); int len = words.mapToInt(String::length).reduce(0, (len1, len2) -> len1 + len2); System.out.println(len); } } This program does not compile and results in compiler error(s) This program prints: onetwothree This program prints: 11 This program throws an IllegalArgumentException Which one of the following options is best suited for generating random numbers in a multi-threaded application? Using java.lang.Math.random() Using java.util.concurrent.ThreadLocalRandom Using java.util.RandomAccess Using java.lang.ThreadLocal<T> Given this code segment: DateTimeFormatter fromDateFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy"); // PARSE_DATE DateTimeFormatter toDateFormat = DateTimeFormatter.ofPattern("dd/MMM/YY"); System.out.println(firstOct2015.format(toDateFormat)); Which one of the following statements when replaced with the comment PARSE_ DATE will result in the code to print “ 10/Jan/15 ”? DateTimeFormatter firstOct2015 = DateTimeFormatter.parse("01/10/2015", fromDateFormat); LocalTime firstOct2015 = LocalTime.parse("01/10/2015", fromDateFormat); Period firstOct2015 = Period.parse("01/10/2015", fromDateFormat); LocalDate firstOct2015 = LocalDate.parse("01/10/2015", fromDateFormat); Consider the following program: import java.util.*; class ListFromVarargs { public static <T> List<T> asList1(T... elements) { ArrayList<T> temp = new ArrayList<>(); for(T element : elements) { temp.add(element); } return temp; } public static <T> List<?> asList2(T... elements) { ArrayList<?> temp = new ArrayList<>(); for(T element : elements) { temp.add(element); } return temp; } public static <T> List<?> asList3(T... elements) { ArrayList<T> temp = new ArrayList<>(); for(T element : elements) { temp.add(element); } return temp; } public static <T> List<?> asList4(T... elements) { List<T> temp = new ArrayList<T>(); for(T element : elements) { temp.add(element); } return temp; } } Which of the asList definitions in this program will result in a compiler error? The definition of asList1 will result in a compiler error The definition of asList2 will result in a compiler error The definition of asList3 will result in a compiler error The definition of asList4 will result in a compiler error None of the definitions (asList1, asList2, asList3, asList4) will result in a compiler error Given this code segment: IntFunction<UnaryOperator<Integer>> func = i -> j -> i * j; // LINE System.out.println(apply); Which one of these statements when replaced by the comment marked with LINE will print 200? Integer apply = func.apply(10).apply(20); Integer apply = func.apply(10, 20); Integer apply = func(10 , 20); Integer apply = func(10, 20).apply(); Given this code segment: List<Map<List<Integer>, List<String>>> list = new ArrayList<>(); // ADD_MAP Map<List<Integer>, List<String>> map = new HashMap<>(); list.add(null); // ADD_NULL list.add(map); list.add(new HashMap<List<Integer>, List<String>>()); // ADD_HASHMAP list.forEach(e -> System. out .print(e + " ")); // ITERATE Which one of the following options is correct? This program will result in a compiler error in line marked with comment ADD_MAP This program will result in a compiler error in line marked with comment ADD_HASHMAP This program will result in a compiler error in line marked with comment ITERATE When run, this program will crash, throwing a NullPointerException in line marked with comment ADD_NULL When run, this program will print the following: null {} {} Given this code snippet: LocalDate dateOfBirth = LocalDate.of(1988, Month.NOVEMBER, 4); MonthDay monthDay = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth()); boolean ifTodayBirthday = monthDay.equals(MonthDay.from(LocalDate.now())); // COMPARE System.out.println(ifTodayBirthday ? "Happy birthday!" : "Yet another day!"); Assume that today’s date is 4 th November 2015. Choose the correct answer based on this code segment. This code will result in a compiler error in the line marked with the comment COMPARE When executed, this code will throw DateTimeException This code will print: Happy birthday! This code will print: Yet another day! Consider the following program: class Base<T> { } class Derived<T> { } class Test { public static void main(String []args) { // Stmt #1 } } Which statements can be replaced with // Stmt#1 and the program remains compilable (choose two): Base<Number> b = new Base<Number>(); Base<Number> b = new Derived<Number>(); Base<Number> b = new Derived<Integer>(); Derived<Number> b = new Derived<Integer>(); Base<Integer> b = new Derived<Integer>(); Derived<Integer> b = new Derived<Integer>(); Which of the following classes in the java.util.concurrent.atomic package inherit from java.lang.Number ? (Select all that apply.) AtomicBoolean AtomicInteger AtomicLong AtomicFloat AtomicDouble Given the class definition: class Student{ public Student(int r) { rollNo = r; } int rollNo; } Choose the correct option based on this code segment: HashSet<Student> students = new HashSet<>(); students.add(new Student(5)); students.add(new Student(10)); System.out.println(students.contains(new Student(10))); This program prints the following: true This program prints the following: false This program results in compiler error(s) This program throws NoSuchElementException Which of the following statements are true regarding resource bundles in the context of localization? (Select ALL that apply.) java.util.ResourceBundle is the base class and is an abstraction of resource bundles that contain locale-specific objects java.util.PropertyResourceBundle is a concrete subclass of java.util.ResourceBundle that manages resources for a locale using strings provided in the form of a property file Classes extending java.util.PropertyResourceBundle must override the getContents() method which has the return type Object [][] java.util.ListResourceBundle defines the getKeys() method that returns enumeration of keys contained in the resource bundle Which of the following statements is true regarding the classes or interfaces defined in the java.util.concurrent package? (Select ALL that apply.) The Executor interface declares a single method execute(Runnable command) that executes the given command at sometime in the future The Callable interface declares a single method call() that computes a result The CopyOnWriteArrayList class is not thread-safe unlike ArrayList that is thread-safe The CyclicBarrier class allows threads to wait for each other to reach a common barrier point Given these two class declarations : class CloseableImpl implements Closeable { public void close() throws IOException { System.out.println("In CloseableImpl.close()"); } } class AutoCloseableImpl implements AutoCloseable { public void close() throws Exception { System.out.println("In AutoCloseableImpl.close()"); } } Choose the correct option based on this code segment : try (Closeable closeableImpl = new CloseableImpl(); AutoCloseable autoCloseableImpl = new AutoCloseableImpl()) { } catch (Exception ignore) { // do nothing } finally { // do nothing } This code segment does not print any output in console This code segment prints the following output: In AutoCloseableImpl.close() This code segment prints the following output: In AutoCloseableImpl.close() In CloseableImpl.close() This code segment prints the following output: In CloseableImpl.close() In AutoCloseableImpl.close() Choose the correct option based on this code segment : List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5); ints.replaceAll(i -> i * i); // LINE System.out.println(ints); This code segment prints: [1, 2, 3, 4, 5] This program prints: [1, 4, 9, 16, 25] This code segment throws java.lang.UnsupportedOperationException This code segment results in a compiler error in the line marked with the comment LINE Choose the correct option for this code snippet : public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { // #1 inputFile.close(); // #2 } catch (FileNotFoundException | IOException e) { // #3 e.printStackTrace(); } } The code snippet will compile without any errors The compiler will report an error at statement marked with the comment #1 The compiler will report an error at statement marked with the comment #2 The compiler will report an error at statement marked with the comment #3 Given this program: import java.time.*; import java.time.temporal.ChronoUnit; class DecadeCheck { public static void main(String []args) { Duration tenYears = ChronoUnit.YEARS.getDuration().multipliedBy(10); Duration aDecade = ChronoUnit.DECADES.getDuration(); assert tenYears.equals(aDecade) : "10 years is not a decade!"; } } Assume that this program is invoked as follows: java DecadeCheck Choose the correct option based on this program: This program does not compile and results in compiler error(s) When executed, this program prints: 10 years is not a decade! When executed, this program throws an AssertionError with the message “10 years is not a decade!” When executed, this program does not print any output and terminates normally Consider the following code segment: while( (ch = inputFile.read()) != VALUE) { outputFile.write( (char)ch ); } Assume that inputFile is of type FileReader , and outputFile is of type FileWriter , and ch is of type int . The method read() returns the character if successful, or VALUE if the end of the stream has been reached. What is the correct value of this VALUE checked in the while loop for end-of-stream? -1 0 255 Integer.MAX_VALUE Integer.MIN_VALUE Consider the following code snippet. String srcFile = "Hello.txt"; String dstFile = "World.txt"; try (BufferedReader inputFile = new BufferedReader(new FileReader(srcFile)); BufferedWriter outputFile = new BufferedWriter(new FileWriter(dstFile))) { int ch = 0; inputFile.skip(6); while( (ch = inputFile.read()) != -1) { outputFile.write( (char)ch ); } outputFile.flush(); } catch (IOException exception) { System.err.println("Error " + exception.getMessage()); } Assume that you have a file named Hello.txt in the current directory with the following contents: Hello World! Which one of the following options correctly describes the behavior of this code segment (assuming that both srcFile and dstFile are opened successfully)? The program will throw an IOException because skip() is called before calling read() The program will result in creating the file World.txt with the contents “World!” in it This program will result in throwing CannotSkipException This program will result in throwing IllegalArgumentException Consider the following code segment: try (BufferedReader inputFile = new BufferedReader(new FileReader(srcFile)); BufferedWriter outputFile = new BufferedWriter(new FileWriter(dstFile))) { // TRY-BLOCK int ch = 0; while( (ch = inputFile.read()) != -1) { // COND-CHECK outputFile.write( (char)ch ); } } catch (Exception exception) { System.err.println("Error in opening or processing file " + exception.getMessage()); } Assume that srcFile and dstFile are Strings. Choose the correct option. This program will get into an infinite loop because the condition check for end-of-stream (checking != -1) is incorrect This program will get into an infinite loop because the variable ch is declared as int instead of char This program will result in a compiler error in line marked with comment TRY-BLOCK because you need to use , (comma) instead of ; (semi-colon) as separator for opening multiple resources This program works fine and copies srcFile to dstFile Given the following definitions: interface InterfaceOne<T> { void foo(); } interface InterfaceTwo<T> { T foo(); } interface InterfaceThree<T> { void foo(T arg); } interface InterfaceFour<T> { T foo(T arg); } public class DateLambda { public static void main(String []args) { // STATEMENT System.out.println(val.foo()); } } Which one of the following statements can be replaced with the line marked with the comment STATEMENT that the program will print the result that is same as the call LocalDateTime.now()? InterfaceOne<LocalDateTime> val = LocalDateTime::now; InterfaceTwo<LocalDateTime> val = LocalDateTime::now; InterfaceThree<LocalDateTime> val = LocalDateTime::now; InterfaceFour<LocalDateTime> val = LocalDateTime::now; Which one of the following statements will compile without errors? Locale locale1 = new Locale.US; Locale locale2 = Locale.US; Locale locale3 = new US.Locale(); Locale locale4 = Locale("US"); Locale locale5 = new Locale(Locale.US); Choose the correct option based on this code segment: String []exams = { "OCAJP 8", "OCPJP 8", "Upgrade to OCPJP 8" }; Predicate isOCPExam = exam -> exam.contains("OCP"); // LINE-1 List<String> ocpExams = Arrays.stream(exams) .filter(exam -> exam.contains("OCP")) .collect(Collectors.toList()); // LINE-2 boolean result = ocpExams.stream().anyMatch(exam -> exam.contains("OCA")); // LINE-3 System.out.println(result); This code results in a compiler error in line marked with the comment LINE-1 This code results in a compiler error in line marked with the comment LINE-2 This code results in a compiler error in line marked with the comment LINE-3 This program prints: true This program prints: false Which one of the following code snippets shows the correct usage of try-with-resources statement? a) public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { //... } catch(IOException ioe) {} } b) public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { //... } finally { } catch(IOException ioe) {} } c) public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { //... } catch(IOException ioe) {} finally { inputFile.close(); } } d) public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { //... } } Two friends are waiting for some more friends to come so that they can go to a restaurant for dinner together. Which synchronization construct could be used here to programmatically simulate this situation? java.util.concurrent.RecursiveTask java.util.concurrent.locks.Lock java.util.concurrent.CyclicBarrier java.util.concurrent.RecursiveAction Choose the correct option based on this program: import java.util.*; public class ResourceBundle_it_IT extends ListResourceBundle { public Object[][] getContents() { return contents; } static final Object[][] contents = { { "1", "Uno" }, { "2", "Duo" }, { "3", "Trie" }, }; public static void main(String args[]) { ResourceBundle resBundle = ResourceBundle.getBundle("ResourceBundle", new Locale("it", "IT", "")); System.out.println(resBundle.getObject(new Integer(1).toString())); } } This program prints the following: Uno This program prints the following: 1 This program will throw a MissingResourceException This program will throw a ClassCastException Given this code segment: Set<String> set = new CopyOnWriteArraySet<String>(); // #1 set.add("2"); set.add("1"); Iterator<String> iter = set.iterator(); set.add("3"); set.add("-1"); while(iter.hasNext()) { System.out.print(iter.next() + " "); } Choose the correct option based on this code segment . This code segment prints the following: 2 1 This code segment the following: 1 2 This code segment prints the following: -1 1 2 3 This code segment prints the following: 2 1 3 -1 This code segment throws a ConcurrentModificationException This code segment results in a compiler error in statement #1 Choose the correct option based on this code segment: Stream<Integer> ints = Stream.of(1, 2, 3, 4); boolean result = ints.parallel().map(Function.identity()).isParallel(); System.out.println(result); This code segment results in compiler error(s) This code segment throws InvalidParallelizationException for the call parallel() This code segment prints: false This code segment prints: true Choose the correct option based on this code segment: Path currPath = Paths.get("."); try (DirectoryStream<Path> javaFiles = Files.newDirectoryStream(currPath, "*.{java}")) { for(Path javaFile : javaFiles) { System.out.println(javaFile); } } catch (IOException ioe) { System.err.println("IO Error occurred"); System.exit(-1); } This code segment throws a PatternSyntaxException This code segment throws an UnsupportedOperationException This code segment throws an InvalidArgumentException This code segment lists the files ending with suffix .java in the current directory Given this code segment: Path aFilePath = Paths.get("D:\\dir\\file.txt"); Iterator<Path> paths = aFilePath.iterator(); while(paths.hasNext()) { System.out.print(paths.next() + " "); } Choose the correct option assuming that you are using a Windows machine and the file D:\dir\file.txt does not exist in the underlying file system. The program throws a FileNotFoundException The program throws an InvalidPathException The program throws an UnsupportedOperationException The program gets into an infinite loop and keeps printing: path element: dir The program prints the following: dir file.txt Which of the following is NOT a problem associated with thread synchronization using mutexes? Deadlock Lock starvation Type erasure Livelock Assume that a thread acquires a lock on an object obj; the same thread again attempts to acquire the lock on the same object obj. What will happen? If a thread attempts to acquire a lock again, it will result in throwing an IllegalMonitorStateException If a thread attempts to acquire a lock again, it will result in throwing an AlreadyLockAcquiredException It is okay for a thread to acquire lock on obj again, and such an attempt will succeed If a thread attempts to acquire a lock again, it will result in a deadlock Which one of the following interfaces is empty (i.e., an interface that does not declare any methods)? java.lang.AutoCloseable interface java.util.concurrent.Callable<T> interface java.lang.Cloneable interface java.lang.Comparator<T> interface Consider the following program and choose the correct option that describes its output: import java.util.concurrent.atomic.AtomicInteger; class Increment { public static void main(String []args) { AtomicInteger i = new AtomicInteger(0); increment(i); System.out.println(i); } static void increment(AtomicInteger atomicInt){ atomicInt.incrementAndGet(); } } 0 1 This program throws an UnsafeIncrementException This program throws a NonThreadContextException What is the output of the following program? class EnumTest { enum Directions { North, East, West, South }; enum Cards { Spade, Hearts, Club, Diamond }; public static void main(String []args) { System.out.println("equals: " + Directions.East.equals(Cards.Hearts)); System.out.println("ordinals: " + (Directions.East.ordinal() == Cards.Hearts.ordinal())); } } equals: false ordinals: false equals: true ordinals: false equals: false ordinals: true equals: true ordinals: true Consider the following program and choose the correct option: import java.util.concurrent.atomic.AtomicInteger; class AtomicVariableTest { private static AtomicInteger counter = new AtomicInteger(0); static class Decrementer extends Thread { public void run() { counter.decrementAndGet(); // #1 } } static class Incrementer extends Thread { public void run() { counter.incrementAndGet(); // #2 } } public static void main(String []args) { for(int i = 0; i < 5; i++) { new Incrementer().start(); new Decrementer().start(); } System.out.println(counter); } } This program will always print 0 This program will print any value between -5 to 5 If you make the run() methods in the Incrementer and Decrementer classes synchronized, this program will always print 0 The program will report compilation errors at statements #1 and #2 Which one of the following statements will compile without any errors? Supplier<LocalDate> now = LocalDate::now(); Supplier<LocalDate> now = () -> LocalDate::now; String now = LocalDate::now::toString; Supplier<LocalDate> now = LocalDate::now; For the following enumeration definition, which one of the following prints the value 2 in the console? enum Pets { Cat, Dog, Parrot, Chameleon }; System.out.print(Pets.Parrot.ordinal()); System.out.print(Pets.Parrot); System.out.print(Pets.indexAt("Parrot")); System.out.print(Pets.Parrot.value()); System.out.print(Pets.Parrot.getInteger()); Assume that the current directory is “D:\workspace\ch14-test”. Choose the correct option based on this code segment: Path testFilePath = Paths.get(".\\Test"); System.out.println("file name:" + testFilePath.getFileName()); System.out.println("absolute path:" + testFilePath.toAbsolutePath()); System.out.println("Normalized path:" + testFilePath.normalize()); file name:Test absolute path:D:\workspace\ch14-test\.\Test Normalized path:Test file name:Test absolute path:D:\workspace\ch14-test\Test Normalized path:Test file name:Test absolute path:D:\workspace\ch14-test\.\Test Normalized path:D:\workspace\ch14-test\.\Test file name:Test absolute path:D:\workspace\ch14-test\.\Test Normalized path:D:\workspace\ch14-test\Test Given this code segment: BufferedReader br = new BufferedReader(new FileReader("names.txt")); System.out.println(br.readLine()); br.mark(100); // MARK System.out.println(br.readLine()); br.reset(); // RESET System.out.println(br.readLine()); Assume that names.txt exists in the current directory, and opening the file succeeds, and br points to a valid object. The content of the names.txt is the following: olivea emma margaret emily Choose the correct option. This code segment prints the following: olivea emma margaret This code segment prints the following: olivea emma olivea This code segment prints the following: olivea emma emma This code segment throws an IllegalArgumentException in the line MARK This code segment throws a CannotResetToMarkPositionException in the line RESET Given this class definition : abstract class Base { public abstract Number getValue(); } Which of the following two options are correct concrete classes extending Base class? class Deri extends Base { protected Number getValue() { return new Integer(10); } } class Deri extends Base { public Integer getValue() { return new Integer(10); } } class Deri extends Base { public Float getValue(float flt) { return new Float(flt); } } class Deri extends Base { public java.util.concurrent.atomic.AtomicInteger getValue() { return new java.util.concurrent.atomic.AtomicInteger(10); } } Which TWO of the following classes are defined in the java.util.concurrent.atomic package? AtomicBoolean AtomicDouble AtomicReference<V> AtomicString AtomicObject<V> Given the following class and interface definitions : class CannotFlyException extends Exception {} interface Birdie { public abstract void fly() throws CannotFlyException; } interface Biped { public void walk(); } abstract class NonFlyer { public void fly() { System.out.print("cannot fly "); } // LINE A } class Penguin extends NonFlyer implements Birdie, Biped { // LINE B public void walk() { System.out.print("walk "); } } Select the correct option for this code segment: Penguin pingu = new Penguin(); pingu.walk(); pingu.fly(); Compiler error in line with comment LINE A because fly() does not declare to throw CannotFlyException Compiler error in line with comment LINE B because fly() is not defined and hence need to declare it abstract It crashes after throwing the exception CannotFlyException When executed, the program prints “walk cannot fly” Given this class definition: class Outer { static class Inner { public final String text = "Inner"; } } Which one of the following expressions when replaced for the text in place of the comment /CODE HERE/ will print the output “Inner” in console? class InnerClassAccess { public static void main(String []args) { System.out.println(/*CODE HERE*/); } } new Outer.Inner().text Outer.new Inner().text Outer.Inner.text new Outer().Inner.text Given this code snippet: String[] fileList = { "/file1.txt", "/subdir/file2.txt", "/file3.txt" }; for (String file : fileList) { try { new File(file).mkdirs(); } catch (Exception e) { System.out.println("file creation failed"); System.exit(-1); } } Assume that the underlying file system has the necessary permissions to create files, and that the program executed successfully without printing the message “file creation failed.” (In the answers, note that the term “current directory” means the directory from which you execute this program, and the term “root directory” in Windows OS means the root path of the current drive from which you execute this program.) Choose the correct option: This code segment will create file1.txt and file3.txt files in the current directory, and file2.txt file in the subdir directory of the current directory This code segment will create file1.txt and file3.txt directories in the current directory and the file2.txt directory in the “subdir” directory in the current directory This code segment will create file1.txt and file3.txt files in the root directory, and a file2.txt file in the “subdir” directory in the root directory This code segment will create file1.txt and file3.txt directories in the root directory, and a file2.txt directory in the “subdir” directory in the root directory Given these class definitions: class Book { public void read() { System.out.println("read!"); } } public class BookUse { // DEFINE READBOOK HERE public static void main(String []args) { new BookUse().readBook(Book::new); } } Which one of the following code segments when replaced with the comment “DEFINE READBOOK HERE” inside the BookUse class will result in printing “read!” on the console? private void readBook(Supplier<? extends Book> book) { book.get().read(); } private static void readBook(Supplier<? extends Book> book) { Book::read; } private void readBook(Consumer<? extends Book> book) { book.accept(); } private void readBook(Function<? extends Book> book) { book.apply(Book::read); } Given the class definition: class Employee { String firstName; String lastName; public Employee (String fName, String lName) { firstName = fName; lastName = lName; } public String toString() { return firstName + " " + lastName; } String getFirstName() { return firstName; } String getLastName() { return lastName; } } Here is a code segment: Employee[] employees = { new Employee("Dan", "Abrams"), new Employee("Steve", "Nash"), new Employee("John", "Nash"), new Employee("Dan", "Lennon"), new Employee("Steve", "Lennon") }; Comparator<Employee> sortByFirstName = ((e1, e2) -> e1.getFirstName().compareTo(e2.getFirstName())); Comparator<Employee> sortByLastName = ((e1, e2) -> e1.getLastName().compareTo(e2.getLastName())); // SORT The sorting needs to be performed in descending order of the first names; when first names are the same, the names should then be sorted in ascending order of the last names. For that, which one of the following code segment will you replace for the line marked by the comment SORT? Stream.of(employees) .sorted(sortByFirstName.thenComparing(sortByLastName)) .forEach(System.out::println); Stream.of(employees) .sorted(sortByFirstName.reversed().thenComparing(sortByLastName)) .forEach(System.out::println); Stream.of(employees) .sorted(sortByFirstName.thenComparing(sortByLastName).reversed()) .forEach(System.out::println); Stream.of(employees) .sorted(sortByFirstName.reversed().thenComparing(sortByLastName).reversed()) .forEach(System.out::println); Given this code snippet: Statement statement = connection.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet resultSet = statement.executeQuery ("SELECT * FROM EMPLOYEE WHERE EMPNAME = \"John\""); resultSet.updateString("EMPNAME", "Jonathan"); // UPDATE Assume that the variable connection points to a valid Connection object and there exists an employee record with EMPNAME value “John”. The resultSet is updated by changing the value of EMPNAME column with the value “Jonathan” instead of “John”. For this change to be reflected in the underlying database, which one of the following statements will you replace with the comment UPDATE ? connection.updateAllResultSets(); resultSet.updateRow(); statement.updateDB(); connection.updateDatabase(); Given these class definitions : class ReadDevice implements AutoCloseable { public void read() throws Exception { System.out.print("read; "); throw new Exception(); } public void close() throws Exception { System.out.print("closing ReadDevice; "); } } class WriteDevice implements AutoCloseable { public void write() { System.out.print("write; "); } public void close() throws Exception { System.out.print("closing WriteDevice; "); } } What will this code segment print? try(ReadDevice rd = new ReadDevice(); WriteDevice wd = new WriteDevice()) { rd.read(); wd.write(); } catch(Exception e) { System.out.print("Caught exception; "); } read; closing WriteDevice; closing ReadDevice; Caught exception; read; write; closing WriteDevice; closing ReadDevice; Caught exception; read; write; closing ReadDevice; closing WriteDevice; Caught exception; read; write; Caught exception; closing ReadDevice; closing WriteDevice; read; Caught exception; closing ReadDevice; closing WriteDevice; Select all the statements that are true about streams (supported in java.util.stream.Stream interface)? Computation on source data is performed in a stream only when the terminal operation is initiated, i.e., streams are “lazy” Once a terminal operation is invoked on a stream, it is considered consumed and cannot be used again Once a stream is created as a sequential stream, its execution mode cannot be changed to parallel stream (and vice versa) If the stream source is modified when the computation in the stream is being performed, then it may result in unpredictable or erroneous results Given the code segment: List<Integer> integers = Arrays.asList(15, 5, 10, 20, 25, 0); // GETMAX Which of the code segments can be replaced for the comment marked with GETMAX to return the maximum value? Integer max = integers.stream().max((i, j) -> i - j).get(); Integer max = integers.stream().max().get(); Integer max = integers.max(); Integer max = integers.stream().mapToInt(i -> i).max(); Given the class definition : class NullableBook { Optional<String> bookName; public NullableBook(Optional<String> name) { bookName = name; } public Optional<String> getName() { return bookName; } } Choose the correct option based on this code segment: NullableBook nullBook = new NullableBook(Optional.ofNullable(null)); Optional<String> name = nullBook.getName(); name.ifPresent(System.out::println).orElse("Empty"); // NULL This code segment will crash by throwing NullPointerException This code segment will print: Empty This code segment will print: null This code segment will result in a compiler error in line marked with NULL Choose the correct option for this code segment : List<String> lines = Arrays.asList("foo;bar;baz", "", "qux;norf"); lines.stream() .flatMap(line -> Arrays.stream(line.split(";"))) // FLAT .forEach(str -> System.out.print(str + ":")); This code will result in a compiler error in line marked with the comment FLAT This code will throw a java.lang.NullPointerException This code will throw a java.util.regex.PatternSyntaxException This code will print foo:bar:baz::qux:norf: Choose the correct option based on this code segment: LocalDate feb28th = LocalDate.of(2015, Month.FEBRUARY, 28); System.out.println(feb28th.plusDays(1)); This program prints: 2015-02-29 This program prints: 2015-03-01 This program throws a java.time.DateTimeException This program throws a java.time.temporal.UnsupportedTemporalTypeException Choose the correct option based on this code segment : List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5); ints.removeIf(i -> (i % 2 ==0)); // LINE System.out.println(ints); This code segment prints: [1, 3, 5] This code segment prints: [2, 4] This code segment prints: [1, 2, 3, 4, 5] This code segment throws java.lang.UnsupportedOperationException This code segment results in a compiler error in the line marked with the comment LINE Given the class definition: class Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } // other methods elided } Which one of the following enforces encapsulation? (Select all that apply.) Make data members x and y private Make the Point class public Make the constructor of the Point class private Remove the getter methods getX() and getY() methods from the Point class Make the Point class static Given the definition: class Sum implements Callable<Long> { // LINE_DEF long n; public Sum(long n) { this.n = n; } public Long call() throws Exception { long sum = 0; for(long longVal = 1; longVal <= n; longVal++) { sum += longVal; } return sum; } } Given that the sum of 1 to 5 is 15, select the correct option for this code segment: Callable<Long> task = new Sum(5); ExecutorService es = Executors.newSingleThreadExecutor(); // LINE_FACTORY Future<Long> future = es.submit(task); // LINE_CALL System.out.printf("sum of 1 to 5 is %d", future.get()); es.shutdown(); This code results in a compiler error in the line marked with the comment LINE_DEF This code results in a compiler error in the line marked with the comment LINE_FACTORY This code results in a compiler error in the line marked with the comment LINE_CALL This code prints: sum of 1 to 5 is 15 Given this class definition: public class AssertCheck { public static void main(String[] args) { int score = 0; int num = 0; assert ++num > 0 : "failed"; int res = score / num; System.out.println(res); } } Choose the correct option assuming that this program is invoked as follows: java –ea AssertCheck This program crashes by throwing java.lang.AssertionError with the message “failed” This program crashes by throwing java.lang.ArithmeticException with the message “/ by zero” This program prints: 0 This program prints “failed” and terminates normally Given this code segment: BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String integer = br.readLine(); // CODE System.out.println(val); Which one of the following statements when replaced by the comment CODE will successfully read an integer value from console? int val = integer.getInteger(); int val = Integer.parseInt(integer); int val = String.parseInt(integer); int val = Number.parseInteger(integer); Which one of the following definitions of the AResource class implementation is correct so that it can be used with try-with-resources statement? a) class AResource implements Closeable { protected void close() /* throws IOException */ { // body of close to release the resource } } b) class AResource implements Closeable { public void autoClose() /* throws IOException */ { // body of close to release the resource } } c) class AResource implements AutoCloseable { void close() /* throws IOException */ { // body of close to release the resource } } d) class AResource implements AutoCloseable { public void close() throws IOException { // body of close to release the resource } } Which of the following are functional interfaces ? (Select all that apply.) a) @FunctionalInterface interface Foo { void execute(); } b) @FunctionalInterface interface Foo { void execute(); boolean equals(Object arg0); } c) @FunctionalInterface interface Foo { boolean equals(Object arg0); } d) interface Foo{} Choose the correct option based on this code segment : Stream<String> words = Stream.of("eeny", "meeny", "miny", "mo"); // LINE_ONE String boxedString = words.collect(Collectors.joining(", ", "[", "]")); // LINE_TWO System.out.println(boxedString); This code results in a compiler error in line marked with the comment LINE_ONE This code results in a compiler error in line marked with the comment LINE_TWO This program prints: [eeny, meeny, miny, mo] This program prints: [eeny], [meeny], [miny], [mo] Choose the correct option based on the following code snippet. Assume that DbConnector.connectToDb() returns a valid Connection object and that the EMPLOYEE table has a column named CUSTOMERID of type VARCHAR(3) . ResultSet resultSet = null; try (Connection connection = DbConnector.connectToDb()) { // LINE_ONE Statement statement = connection.createStatement(); resultSet = statement.executeQuery ("SELECT * FROM CUSTOMER WHERE CUSTOMERID = 1212"); // LINE_TWO } while (resultSet.next()){ // LINE_THREE resultSet.getString("CUSTOMERID"); } This code results in a compiler error in line marked with the comment LINE_ONE This code results in a compiler error in line marked with the comment LINE_TWO This code results in a compiler error in line marked with the comment LINE_THREE This code prints "1212" on the console and terminates This code gets into an infinite loop and keeps printing "1212" on the console This code throws SQLException Given this code snippet: public static Connection connectToDb() throws SQLException { String url = "jdbc:mysql://localhost:3306/"; String database = "addressBook"; String userName = "root"; String password = "mysql123"; // CONNECT_TO_DB } Which one of the following statements will you replace with the comment CONNECT_TO_DB to create a Connection object? return DatabaseManager.getConnection(url, database, userName, password); return Connection.getConnection(url, database, userName, password); return DriverManager.getConnection(url + database, userName, password); return DatabaseDriver.getConnection(url + database, userName, password); Choose the correct option based on this code segment: Path path = Paths.get("file.txt"); // READ_FILE lines.forEach(System.out::println); Assume that a file named “file.txt” exists in the directory in which this code segment is run and has the content “hello”. Which one of these options can be replaced by the text READ_FILE that will successfully read the “file.txt” and print “hello” on the console? List<String> lines = Files.lines(path); Stream<String> lines = Files.lines(path); Stream<String> lines = File.readLines(path); Stream<String> lines = Files.readAllLines(path);
答案纸
| 问题编号 | 回答 | 问题编号 | 回答 | 问题编号 | 回答 |
|---|---|---|---|---|---|
| one | Thirty-one | Sixty-one | |||
| Two | Thirty-two | Sixty-two | |||
| three | Thirty-three | Sixty-three | |||
| four | Thirty-four | Sixty-four | |||
| five | Thirty-five | Sixty-five | |||
| six | Thirty-six | Sixty-six | |||
| seven | Thirty-seven | Sixty-seven | |||
| eight | Thirty-eight | sixty-eight | |||
| nine | Thirty-nine | sixty-nine | |||
| Ten | Forty | Seventy | |||
| Eleven | Forty-one | Seventy-one | |||
| Twelve | forty-two | seventy-two | |||
| Thirteen | Forty-three | Seventy-three | |||
| Fourteen | forty-four | Seventy-four | |||
| Fifteen | Forty-five | Seventy-five | |||
| Sixteen | Forty-six | Seventy-six | |||
| Seventeen | Forty-seven | Seventy-seven | |||
| Eighteen | Forty-eight | seventy-eight | |||
| Nineteen | forty-nine | Seventy-nine | |||
| Twenty | Fifty | Eighty | |||
| Twenty-one | Fifty-one | Eighty-one | |||
| Twenty-two | fifty-two | Eighty-two | |||
| Twenty-three | Fifty-three | Eighty-three | |||
| Twenty-four | Fifty-four | Eighty-four | |||
| Twenty-five | Fifty-five | eighty-five | |||
| Twenty-six | fifty-six | ||||
| Twenty-seven | Fifty-seven | ||||
| Twenty-eight | Fifty-eight | ||||
| Twenty-nine | Fifty-nine | ||||
| Thirty | Sixty |
答案和解释
d) This code segment does not print anything on the console The limit() method is an intermediate operation and not a terminal operation. Since there is no terminal operation in this code segment, elements are not processed in the stream and hence it does not print anything on the console. b) while( (ch = inputFile.read()) != -1) { The read() method returns -1 when the file reaches the end. Why other options are wrong: Option a) Since ch is of type int, it cannot be compared with null. Option c) With the check != 0, the program will never terminate since inputFile.read() returns -1 when it reaches end of the file. Option d) Using the identifier EOF will result in a compiler error. a) Base Derived DeriDerived Whenever a class gets instantiated, the constructor of its base classes (the constructor of the root of the hierarchy gets executed first) gets invoked before the constructor of the instantiated class. d) This code prints: Awaiting Awaiting Awaiting Let's play There are three threads expected in the CyclicBarrier because of the value 3 given as the first argument to the CyclicBarrier constructor. When a thread executes, it prints “Awaiting” and awaits for the other threads (if any) to join. Once all three threads join, they cross the barrier and the message “Let's play” gets printed on the console. c) private Point() { this(0, 0); } Options a) and b) Both the calls super() and this() cannot be provided in a constructor Option d) The call this(); will result in a recursive constructor invocation for Point() constructor (and hence the compiler will issue an error) Option e) You cannot refer to an instance field x while explicitly invoking a constructor using this keyword b) Removing Stmt-1 will make the program compilable and it will print the following: Base: Hello Derived. c) Removing Stmt-2 will make the program compilable and it will print the following: Base Derived d) Removing both Stmt-1 and Stmt-2 will make the program compilable and it will print the following: Base Derived Why other options are wrong: Option a) If you remove Stmt-1, a call to super(s) will result in printing Base: Hello, and then constructor of the Derived class invocation will print Derived. Hence it does not print: Base Derived. Option e) If you remove Stmt-1 and Stmt-2, you will get a compilable program but it will result in printing: Base Derived and not Base: Hello Derived. a) The compiler will report an error at statement line marked with the comment #1 Statement #1 will result in a compiler error since the keyword protected is not allowed inside a method body. You cannot provide access specifiers (public, protected, or private) inside a method body. Why other options are wrong: Option b) It is acceptable to extend a base class and hence there is no compiler error in line marked with comment #2. Option c) It is acceptable to pass null to printf function hence there is no compiler error in line marked with comment #2. Option d) This program will not compile cleanly and hence this option is wrong. c) int years = Period.between(joiningDate, now).getYears(); The between() method in Period returns a Period object. The getYears() method called on the returned Period returns an int. Hence, option c) that declares years as int is the correct option. Using the other three options will result in compiler errors because the getYears() method of Period return an int. d) Outer.Inner inner = new Outer().new Inner(); Option d) uses the correct syntax for instantiating Outer and Inner classes. The other three options will result in compiler error(s). c) This program runs and prints 10 An inner class can access even the private members of the outer class. Similarly, the private variable belonging to the inner class can be accessed in the outer class. Why other options are wrong: Options a) and b) are wrong because this program compiles without any errors. The variable mem is initialized to value 10 and that gets printed by the program (and not 0) and hence Option d) is wrong. e) When executed, this program prints the following: yes, instance of AnEnum yes, instance of EnumBase yes, instance of Enum An enumeration can implement an interface (but cannot extend a class, or cannot be a base class). Each enumeration constant is an object of its enumeration type. An enumeration automatically extends the abstract class java.util.Enum. Hence, all the three instanceof checks succeed. Why other options are wrong: This program compiles cleanly and hence options a) and b) are wrong. Options c) and d) do not provide the complete output of the program and hence they are also incorrect. a) An enum can have private constructor c) An enum can have public methods and fields d) An enum can implement an interface Why other options are wrong: Option b) An enum cannot have public constructor(s) Option e) An enum cannot extend a class c) The program will report a compilation error at statement marked with the comment #3 Statements marked with the comment #1 and #2 will not result in any compiler errors; only access to the variable var will generate a compiler error since the access is ambiguous (since the variable is declared in both base1 and base2). c) The line marked with comment THREE will result in a compiler error Options a) and b) For the substitution to succeed, the type substituted for the wildcard ? should be DI or one of its super types. Option c) The type DDI is not a super type of DI, so it results in a compiler error. Option d) The type argument is not provided, meaning that C is a raw type in the expression new C(). Hence, this will elicit a compiler warning, but not an error. c) class X <T extends DI> { } The keyword extends is used to specify the upper bound for type T; with this, only the classes or interfaces implementing the interface DI can be used as a replacement for T. Note that the extends keyword is used for any base type—irrespective of whether the base type is a class or an interface. c) A Factory class may use Singleton pattern A Factory class generates the desired type of objects on demand. Hence, it might be required that only one Factory object exists; in this case, Singleton can be employed in a Factory class. Why other options are wrong: a) A Singleton class needs to have a static member to return a singleton instance b) A Singleton class must declare its constructor(s) private to ensure that they are not instantiated d) A static method (typically named getInstance()) with public access may need to be provided to get the instance of the Singleton class. b) Class Test is related with ClassC with a composition relationship. When a class inherits from another class, they share an IS-A relationship. On the other hand, if a class uses another class (by declaring an instance of another class), then the first class has a HAS-A relationship with the used class. c) The program prints the following: Brazil China India Russia. For the sort() method, null value is passed as the second argument, which indicates that the elements’ “natural ordering” should be used. In this case, natural ordering for Strings results in the strings sorted in ascending order. Note that passing null to the sort() method does not result in a NullPointerException. The statement marked with COMPARE_TO will compile without errors. Note that the variable comparer is unused in this code segment. b) class Q<T> { T mem; public Q(T arg) { mem = arg; } } Option a) You cannot make a static reference of type T in a generic class. Option c) and d) You cannot instantiate the type T or T[] using new operator in a generic class. b) public Object[][] getContents() { return new Object[][] { { "1", "Uno" }, { "2", "Duo" }, { "3", "Trie" }}; } The getContents() method is declared in ListResourceBundle as follows: protected abstract Object[][] getContents() The other three definitions are incorrect overrides and will result in compiler error(s). a) Iterable<T> The interface Iterable<T> declares this single method: Iterator<T> iterator(); This iterator() method returns an object of type Iterator. A class must implement Iterable for using its object in a for-each loop. Though Iterable interface (in Java 8) defines forEach() and spliterator() methods, they are default methods and not static methods. Why other options are wrong: Option b) The Iterator<T> interface declares abstract methods hasNext() and next(), and defines default methods remove() and forEachRemaining(). Option c) The Enumeration<T> interface declares hasMoreElements() and nextElement() methods. Option d) There is no interface named ForEach<T> in the Java core library. c) This program prints: 11 This program compiles without any errors. The variable words point to a stream of Strings. The call mapToInt(String::length) results in a stream of Integers with the length of the strings. One of the overloaded versions of reduce() method takes two arguments: T reduce(T identity, BinaryOperator<T> accumulator); The first argument is the identity value, which is given as the value 0 here. The second operand is a BinaryOperator match for the lambda expression (len1, len2) -> len1 + len2. The reduce() method thus adds the length of all the three strings in the stream, which results in the value 11. b) Using java.util.concurrent.ThreadLocalRandom java.lang.Math.random()is not efficient for concurrent programs. Using ThreadLocalRandom results in less overhead and contention when compared to using Random objects in concurrent programs (and hence using this class type is the best option in this case). java.util.RandomAccess is unrelated to random number generation. This interface is the base interface for random access data structures and is implemented by classes such as Vector and ArrayList. java.lang.ThreadLocal<T> class provides support for creating thread-local variables. d) LocalDate firstOct2015 = LocalDate.parse("01/10/2015", fromDateFormat); You need to use LocalDate for parsing the date string given in the DateTimeFormatter variable fromDateFormat (with the format string MM/dd/yyyy”). Other options will not compile. b) The definition of asList2 will result in a compiler error. In the asList2 method definition, temp is declared as ArrayList>. Since the template type is a wild-card, you cannot put any element (or modify the container). Hence, the method call temp.add(element); will result in a compiler error. a) Integer apply = func.apply(10).apply(20); The IntFunction<R> takes an argument of type int and returns a value of type R. The UnaryOperator<T> takes an argument of type T and returns a value of type T. The correct way to invoke func is to call func.apply(10).apply(10) (the other three options do not compile). The first call apply(10) results in an Integer object that is passed to the lambda expression; calling apply(20) results in executing the expression (i * j) that evaluates to 200. The other three options will result in compiler error(s). e) When run, this program will print the following: null {} {} The lines marked with comments ADD_MAP and ADD_HASHMAP are valid uses of the diamond operator to infer type arguments. Calling the add() method passing null does not result in a NullPointerException. The program, when run, will successfully print the output null {} {} (null output indicates a null value was added to the list, and the {} output indicates that Map is empty). c) This code will print: Happy birthday! This code gets the month-and-day components from the given LocalDate and creates a MonthDay object. Another way to create a MonthDay object is to call the from() method and pass a LocalDate object. The equals() method compares if the month and date components are equal and if so returns true. Since the month and day components are equal in this code (assuming that the today’s date is 4th November 2015 as given in the question), it results in printing “Happy birthday!”. a) Base<Number> b = new Base<Number>(); f) Derived<Integer> b = new Derived<Integer>(); Note that Base and Derived are not related by an inheritance relationship. Further, for generic type parameters, subtyping doesn’t work: you cannot assign a derived generic type parameter to a base type parameter. b) AtomicInteger c) AtomicLong Classes AtomicInteger and AtomicLong extend Number class. Why other options are wrong: Option a) AtomicBoolean does not extend java.lang.Number. Options d) and e) Classes named as AtomicFloat or AtomicDouble do not exist in the java.util.concurrent.atomic package. b) This program prints the following: false Since methods equals() and hashcode() methods are not overridden in the Student class, the contains() method will not work as intended and prints false. a) ResourceBundle is the base class and is an abstraction of resource bundles that contain locale-specific objects b) java.util.PropertyResourceBundle is a concrete subclass of java.util.ResourceBundle that manages resources for a locale using strings provided in the form of a property file d) java.util.ListResourceBundle defines the getKeys() method that returns enumeration of keys contained in the resource bundle The option c) is not to be selected. There is no such method named getContents() method that has the return type Object [][]. It has the method getKeys() that returns an enumeration of keys contained in the resource bundle. It is classes that extend java.util.ListResourceBundle (and not java.util.PropertyResourceBundle as given in this option) that must override the getContents() method that has the return type Object [][]. a) TheExecutor interface declares a single method execute(Runnable command) that executes the given command at some time in the future b) The Callable interface declares a single method call() that computes a result d) The CyclicBarrier class allows threads to wait for each other to reach a common barrier point These three options are true. Option c) is incorrect because the CopyOnWriteArrayList class is thread-safe whereas ArrayList class is not thread-safe. c) This code segment prints the following output: In AutoCloseableImpl.close() In CloseableImpl.close() The types implementing AutoCloseable can be used with a try-with-resources statement. The Closeable interface extends AutoCloseable, so classes implementing Closeable can also be used with a try-with-resources statement. The close() methods are called in the opposite order when compared to the order of resources acquired in the try-with-resources statement. So, this program calls the close() method of AutoCloseableImpl first, and after that calls the close() method on the CloseableImpl object. b) This program prints: [1, 4, 9, 16, 25] The replaceAll() method (added in Java 8 to the List interface) takes an UnaryOperator as the argument. In this case, the unary operator squares the integer values. Hence, the program prints [1, 4, 9, 16, 25]. The underlying List object returned by Arrays.asList() method can be modified using the replaceAll() method and it does not result in throwing java.lang.UnsupportedOperationException. d) The compiler will report an error at the statement marked with the comment #3 Both of the specified exceptions belong to the same hierarchy (FileNotFoundException derives from an IOException), so you cannot specify both exceptions together in the multi-catch handler block. It is not a compiler error to explicitly call close() method for a FileReader object inside a try-with-resources block. d) When executed, this program does not print any output and terminates normally The program compiles cleanly without any errors. Assertions are disabled by default. Since assertions are not enabled when invoking this program, it does not evaluate the assert expression. Hence, the program terminates normally without printing any output on the console. a) -1 The read() method returns the value -1 if end-of-stream (EOS) is reached, which is checked in this while loop. b) The program will result in creating the file World.txt with the contents “World!” in it. The method call skip(n)skips n bytes (i.e., moves the buffer pointer by n bytes). In this case, 6 bytes need to be skipped, so the string “Hello” is not copied in the while loop while reading and writing the file contents. Why other options are wrong: Option a) The skip() method can be called before the read() method. Option c) No exception named CannotSkipException exists. Option d) The skip() method will throw an IllegalArgumentException only if a negative value is passed. d) This program works fine and copies srcFile to dstFile Why other options are wrong: Options a) and b) This program does not get into an infinite loop because the condition check for end-of-stream (checking != -1) is correct and the variable ch needs to be declared as int (and not char). Option c) You can use ; (semi-colon) as separator for opening multiple resources in try-with-resources statement. b) InterfaceTwo<LocalDateTime> val = LocalDateTime::now; The method now() in LocalDateTime is declared with the signature: LocalDateTime now() The matching functional interface should also have an abstract method that takes no argument and returns a value of type T. Since InterfaceTwo has the abstract method declared as T foo(), the statement InterfaceTwo<LocalDateTime> val = LocalDateTime::now; succeeds. From the interface, the method can be invoked with val.foo(); since val refers to LocalDateTime::now, and it is equivalent to making the call LocalDateTime.now(). b) Locale locale2 = Locale.US; The static public final Locale US member in the Locale class is accessed using the expression Locale.US, as in option b). The other options will result in compiler error(s). a) This code results in a compiler error in line marked with the comment LINE-1 The functional interface Predicate<T> takes type T as the generic parameter that is not specified in LINE-1. This results in a compiler error because the lambda expression uses the method contains() in the call exam.contains(“OCP”). If Predicate<String> were specified (as in Predicate isOCPExam = exam -> exam.contains("OCP")), this code segment would compile without errors, and when executed will print “false”. a) public static void main(String []files) { try (FileReader inputFile = new FileReader(new File(files[0]))) { //... } catch(IOException ioe) {} } Why other options are wrong:
- 选项 b)在 catch 块之前提供 finally,这将导致一个编译器错误。
- 选项 c)在语句
inputFile.close()中使用了在 finally 块中不可访问的变量inputFile,从而导致编译器错误。选项 d)该上下文中所需的catch块在代码中缺失(因为 try 块代码可能会抛出IOException),因此是不正确的用法。
c) java.util.concurrent.CyclicBarrier CyclicBarrieris used when threads may need to wait at a predefined execution point until all other threads reach that point. This construct matches the given requirements. Why other options are wrong:
- 选项 a)和 d)
java.util.concurrent.RecursiveTask和java.util.concurrent.RecursiveAction在 fork-join 框架中执行任务的上下文中使用。 - 选项 b)
java.util.concurrent.locks.Lock类为锁定和解锁提供了比使用synchronized关键字更好的抽象。
a) This program prints the following: Uno This program correctly extends ListResourceBundle and defines a resource bundle for the locale it_IT. The getObject() method takes String as an argument; this method returns the value of the matching key. The expression new Integer(1).toString() is equivalent of providing the key “1”, so the program prints Uno in the console. a) This code segment prints the following: 2 1 This code segment modifies the underlying CopyOnWriteArrayList container object using the add() method. After adding the elements “2” and “1”, the iterator object is created. After creating this iterator object, two more elements are added, so internally a copy of the underlying container is created due to this modification to the container. But the iterator still refers to the original container that had two elements. So, this program results in printing 2 and 1. If a new iterator is created after adding these four elements, it will iterate over all those four elements. d) This code segment prints: true The stream pointed by ints is a sequential stream because sequential is the default execution mode. The call to parallel() method changes the execution mode to parallel stream. The isParallel() method returns true because the current execution mode of the stream is parallel. Why other options are wrong: Option a) This code compiles without errors. The call to map(Function.identity()) is acceptable because the argument Function.identity() just returns the same stream element it is passed with. Option b) It is possible to change the execution mode of a stream after it is created, and it does not result in throwing any exceptions. Option c) The isParallel() method returns the current execution mode and not the execution mode when the stream was created. So the isParallel() method returns true in this code (and not false as given in this option). d) This code segment lists the files ending with suffix .java in the current directory The path “.” specifies the current directory. The pattern “*.{java}" matches file names with suffix .java. e) This code segment prints the following: dir file.txt The name elements in a path object are identified based on the separators. Note: To iterate name elements of the Path object does not actually require that the corresponding files/directories must exist, so it will not result in throwing any exceptions. c) Type erasure Deadlocks, lock starvation, and livelocks are problems that arise when using mutexes for thread synchronization. Type erasure is a concept related to generics where the generic type information is lost once the generic type is compiled. c) It is okay for a thread to acquire lock on obj again, and such an attempt will succeed Java locks are reentrant: a Java thread, if it has already acquired a lock, can acquire it again, and such an attempt will succeed. No exception is thrown and no deadlock occurs for this case. c) java.lang.Cloneable interface From the documentation of clone() method: “By convention, classes that implement this interface should override the Object.clone() method. Note that this interface does not contain the clone method.” Why other options are wrong:
- 选项 a)
AutoCloseable接口声明了close()方法。 - 选项 b)
Callable声明call()方法。 - 选项 d)
Comparator<T>接口声明了compare()和equals()方法。
b) 1 The call atomicInt.incrementAndGet(); mutates the integer value passed through the reference variable atomicInt, so the changed value is printed in the main() method. Note that AtomicInteger can be used in thread or non-thread context though it is not of any practical use when used in single-threaded programs. c) equals: false ordinals: true The equals() method returns true only if the enumeration constants are the same. In this case, the enumeration constants belong to different enumerations, so the equals() method returns false. However, the ordinal values of the enumeration constants are equal since both are second elements in their respective enumerations. b) This program will print any value between −5 to 5 You have employed AtomicInteger, which provides a set of atomic methods such as incrementAndGet() and decrementAndGet(). Hence, you will always get 0 as the final value of counter. However, depending on thread scheduling, the intermediate counter values may be anywhere between −5 to +5, Hence the output of the program can range between −5 and +5. d) Supplier<LocalDate> now = LocalDate::now; The now() method defined in LocalDate does not take any arguments and returns a LocalDate object. Hence, the signature of now() method matches that of the only abstract method in the Supplier interface: T get(). Hence, the method reference Local::now can be assigned to Supplier<LocalDate> and the statement compiles without any errors. Other options show improper use of method reference and they will result in compiler error(s). a) System.out.print(Pets.Parrot.ordinal()); The ordinal() method prints the position of the enumeration constant within an enumeration and hence it prints 2 for this program. Why other options are wrong:
- 选项 b)调用
print(Pets.Parrot);将字符串“Parrot”打印到控制台 - 选项 c)、d)和 e)在
Enum中没有名为indexAt()、value()或getInteger()的方法
a) file name:Test absolute path:D:\workspace\ch14-test\.\Test Normalized path:Test The absolute path adds the path from the root directory; however, it does not normalize the path. Hence, “.\” will be retained in the resultant path. On the other hand, the normalize() method normalizes the path but does not make it absolute. c) This code segment prints the following: olivea emma emma The method void mark(int limit) in BufferedReader marks the current position for resetting the stream to the marked position. The argument limit specifies the number of characters that may be read while still preserving the mark. This code segment marks the position after “olivea” is read, so after reading “emma,” when the marker is reset and the line is read again, it reads “emma” once again. b) class Deri extends Base { public Integer getValue() { return new Integer(10); } } d) class Deri extends Base { public java.util.concurrent.atomic.AtomicInteger getValue() { return new java.util.concurrent.atomic.AtomicInteger(10); } } Option b) makes use of a co-variant return type (note that Integer extends Number), and defines the overriding method correctly. Option d) makes use of co-variant return type (note that AtomicInteger extends Number), and defines the overriding method correctly. Why the other two options are wrong:
- 选项 a)试图通过在基方法为公共方法时声明方法受保护来分配较弱的访问权限,因此是不正确的(导致编译器错误)。
- 在选项 c)中,方法
Float getValue(float flt)没有覆盖Base中的getValue()方法,因为签名不匹配,所以它是不正确的(导致编译器错误)。
a) AtomicBoolean and c) AtomicReference<V> The class AtomicBoolean supports atomically updatable Boolean values. The class AtomicReference supports atomically updatable references of type V. Classes AtomicDouble, AtomicString, and AtomicObject are not part of the java.util.concurrent.atomic package. d) When executed, the program prints “walk cannot fly” In order to override a method, it is not necessary for the overridden method to specify an exception. However, if the exception is specified, then the specified exception must be the same or a subclass of the specified exception in the method defined in the super class (or interface). a) new Outer.Inner().text The correct way to access fields of the static inner class is to use the inner class instance along with the outer class, so new Outer.Inner().text will do the job. d) This code segment will create file1.txt and file3.txt directories in the root directory, and a file2.txt directory in the “subdir” directory in the root directory. The mkdirs() method creates a directory for the given name. Since the file names have / in them, the method creates directories in the root directory (or root path for the Windows drive based on the path in which you execute this program). a) private void readBook(Supplier<? extends Book> book) { book.get().read(); } The Supplier<T> interface declares the abstract method get(). The get() method does not take any arguments and returns an object of type T. Hence, the call book.get().read() succeeds and prints “read!” on the console. Why other options are wrong: Option b) Method references can be used in places where lambda expressions can be used. Hence, this code segment will result in a compiler error. Option c) The accept() method in the Consumer<T> interface requires an argument to be passed – since it is missing here, it will result in a compiler error. Option d) The Function<T, R> interface takes two type parameters and hence this method definition will result in a compiler error. b) Stream.of(employees) .sorted(sortByFirstName.reversed().thenComparing(sortByLastName)) .forEach(System.out::println); The sortByFirstName is a Comparator that sorts names by the Employee’s first name. Because we need to sort the names in descending order, we need to call the reversed() method. After that, we need to sort the last names in ascending order, and hence we can call thenComparing(sortByLastName). b) resultSet.updateRow() ; The call updateRow() on the ResultSet object updates the database. Other options will not compile. a) read; closing WriteDevice; closing ReadDevice; Caught exception; The read() method of ReadDevice throws an exception, and hence the write() method of WriteDevice is not called. The try-with-resources statement releases the resources in the reverse order from which they were acquired. Hence, the close() for WriteDevice is called first, followed by the call to the close() method for ReadDevice. Finally, the catch block prints “Caught exception;” to the console. a) Computation on source data is performed in a stream only when the terminal operation is initiated, i.e., streams are “lazy” b) Once a terminal operation is invoked on a stream, it is considered consumed and cannot be used again d) If the stream source is modified when the computation in the stream is being performed, then it may result in unpredictable or erroneous results These three statements are true about streams. Option c) is not correct. Once a stream is created as a sequential its execution mode can be changed to parallel stream by calling parallel() method. Similarly, once a parallel stream is created, you can make it a sequential stream by calling sequential() method. a) Integer max = integers.stream().max((i, j) -> i - j).get(); Calling stream() method on a List<Integer> object results in a stream of type Stream<Integer>. The max() method takes a Comparator as the argument that is provided by the lambda expression (i, j) -> i - j. The max() method returns an Optional<Integer> and the get() method returns an Integer value. Why other options are wrong:
- 选项 b)
Stream中的max()方法需要将一个Comparator作为参数传递 - 选项 c)
List<Integer>中没有max()方法 - 选项 d)
mapToInt()方法返回一个IntStream,但是max()方法返回一个OptionalInt,因此它不能被赋值给Integer(如上下文中所要求的)
d) This program will result in a compiler error in line marked with NULL The ifPresent() method for Optional takes a Consumer as the argument and returns void. Hence, it is not possible to chain the orElse() method after calling the ifPresent() method. d) This code will print foo:bar:baz::qux:norf: The flatMap() method flattens the streams by taking the elements in the stream. The elements in the given strings are split using the separator “;” and the elements from the resulting string stream are collected. The forEach() method prints the resulting strings. Why other options are wrong: Option a) This code does not issue any compiler errors Option b) This Splitting an empty string does not result in a null, and hence this code does not throw NullPointerException. Option c) The syntax of the given regular expression is correct and hence it does not result in PatternSyntaxException. b) This program prints: 2015-03-01 Since 2015 is not a leap year, there are only 28 days in February. Hence adding a day from 28th February 2015 results in 1st March 2015 and that is printed. d) This code segment throws java.lang.UnsupportedOperationException The underlying List object returned by Arrays.asList() method is a fixed-size list and hence we cannot remove elements from that list. Hence calling removeIf() method on this list results in throwing an UnsupportedOperationException. a) Make data members x and y private Publicly visible data members violate encapsulation since any code can modify the x and y values of a Point object directly. It is important to make data members private to enforce encapsulation. Why other options are wrong:
- 选项 b)、c)和 d)将
Point类设为公共,将该类的构造函数设为私有,或者移除 getter 方法,这些都无助于强制封装。 - 选项 e)不能声明静态类。
d) This code prints: sum of 1 to 5 is 15 This code correctly uses Callable<T>, ExecutorService, and Future<T> interfaces and the Executors class to calculate the sum of numbers from 1 to 5. c) This program prints: 0 The condition within the assert statement ++num > 0 holds true because num’s value is 1 with the pre-increment expression ++num. The expression 0 / 1 results in the value 0 and hence the output. Why other options are wrong:
- 选项 a)和 d)断言条件成立;因此既不会抛出
java.lang.AssertionError,也不会打印出“失败”消息 - 因为断言是通过传递选项“-ea”来启用的,所以这不会导致被零除。如果断言没有被禁用,它将会因抛出消息“
/ by zero”而崩溃
b) int val = Integer.parseInt(integer) ; Using the method Integer.parseInt(String) is the correct way to get an int value from a String object. The other three options will not compile. d) class AResource implements AutoCloseable { public void close() throws IOException { // body of close to release the resource } } AutoCloseable is the base interface of the Closeable interface; AutoCloseable declares close as void close() throws Exception; In Closeable, it is declared as public void close() throws IOException;. For a class to be used with try-with-resources, it should both implement Closeable or AutoCloseable and correctly override the close() method. Option a) declares close() protected; since the close() method is declared public in the base interface, you cannot reduce its visibility to protected, so this will result in a compiler error. Option b) declares autoClose(); a correct implementation would define the close() method. Option c) declares close() with default access; since the close method is declared public in the base interface, you cannot reduce its visibility to default accesses, so it will result in a compiler error. Option d) is a correct implementation of the AResource class that overrides the close() method. a)@FunctionalInterface interface Foo { void execute(); } b) @FunctionalInterface interface Foo { void execute(); boolean equals(Object arg0); } The interface in option a) declares exactly one abstract method and hence it is a functional interface. In option b) note that equals() method belongs to Object class, which is not counted as an abstract method required for a functional interface. Hence, the interface in option b) has only one abstract method and it qualifies as a functional interface. Why other options are wrong:
- 选项 c)接口没有声明抽象方法,因此它不是函数式接口。
- 选项 d)接口没有任何方法,因此它不是一个函数式接口。
c) This program prints: [eeny, meeny, miny, mo] Stream.of() method takes a variable length argument list of type T and it returns a Stream<T>. The joining() method in Collectors class takes delimiter, prefix, and suffix as arguments: joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) Hence, the expression Collectors.joining(", ", "[", "]") joins the strings with commas and encloses the resulting string within ‘[‘ and ‘]’. f) This code throws SQLException The try-with-resources block is closed before the while statement executes. Hence, call resultSet.next() results in making a call on the closed ResultSet object, thereby throwing an SQLException. c) return DriverManager.getConnection(url + database, userName, password); The getConnection() method in DriverManager takes three String arguments and returns a Connection: Connection getConnection(String url, String user, String password) Hence, option c) is the correct answer. The other three options will result in compiler errors. b) Stream<String> lines = Files.lines(path); The lines(Path) method in Files class takes a Path and returns Stream<String>. Hence option b) is the correct answer. Option a) The code segment results in a compiler error because the return type of lines() method is Stream<String> and not List<String>. Option c) There is no such method named readLines(Path) in Files that returns a Stream<String> and hence it results in a compiler error. Option d) The readAllLines(Path) method returns a List<String> and not Stream<String> and hence the given statement results in a compiler error.