[原创]Java基础知识记录(2)

前言:本文『很傻很天真』,任何稍有Java编程经验的都不用看了。
文章来源:http://www.codelast.com/
 创建一个Set时,如何初始化其中的元素
如果在创建一个Set之后,再用add()方法向Set中添加元素,就显得比较麻烦了。通过使用Google Guava库,可以在初始化的时候就向其添加若干元素:

Set<String> s = Sets.newHashSet("99""100")

这样创建出的s就会包含99和100这两个元素。

 jar包中的.class文件,为什么有的文件名类似于 ***$1.class

$后面跟数字是匿名类编译出来的,$后面跟文字是内部类编译出来的。

文章来源:http://www.codelast.com/
 java.lang.OutOfMemoryError: GC overhead limit exceeded错误
出现这个错误的时候,程序可能接着就挂掉了。要关掉该功能,可以在程序启动的时候传入参数:

java -XX:-UseGCOverheadLimit (后面省略)

 使用Log4j打印格式化的字符串时的高效率写法
如果你使用Log4j来打印日志,字符串中需要format一些变量,例如:

int countNum = 9999;
LOG.debug(String.format("Count: %d", countNum));

这样并不是最有效率的写法,如下写法更高效:

int countNum = 9999;
LOG.debug("Count: {}", countNum);

 单元测试时,提示“java.lang.SecurityException: Prohibited package name: java.com.xxx”错误的原因
这是因为package名不能以java开头,修改后再重新运行单元测试即可解决此问题。

文章来源:http://www.codelast.com/
 同一个jar包中的多个client程序,有一个client能连上Zookeeper server的解决办法
我最后还是没找到原因,但是解决了。可以尝试如下解决办法:

①用 ps -ef | grep zookeeper 查看当前有几个Zookeeper进程,如果可以的话,把它们全部kill掉,再用Zookeeper安装目录下的 bin/zkServer.sh 脚本来启动。在启动之前,修改 conf/zoo.cfg 配置文件,添加如下一行:

maxClientCnxns=300

此参数含义为:
单个客户端与单台服务器之间的连接数的限制,是IP级别的,默认是60,如果设置为0,那么表明不作任何限制。请注意这个限制的使用范围,仅仅是单台客户端机器与单台Zookeeper服务器之间的连接数限制,不是针对指定客户端IP,也不是ZK集群的连接数限制,也不是单台ZK对所有客户端的连接数限制。
②用 bin/zkServer.sh 脚本来启动 Zookeeper server:

./zkServer.sh start

③查看server是否已经启动了,如果是,则重新用client程序连接Zookeeper server。

 Java正则截取书名号里的内容
假设有如下字符串:

今天去看好评如潮的《变形金刚》这部电影

那么要获取书名号里的内容“变形金刚”,可以用Java这样干:

Pattern MY_PATTERN = Pattern.compile(".*《(.+)》.*");

String str = "今天去看好评如潮的《变形金刚》这部电影";
String result = "";

Matcher matcher = MY_PATTERN.matcher(str);
if (matcher.matches()) {
    result = matcher.group(1);
}

结果就保存在了result中。
文章来源:http://www.codelast.com/
 Java计算一个字符串的MD5值
org.apache.commons.codec.digest包(jar包名类似于commons-codec-1.6.jar)中的DigestUtils.md5Hex()方法来计算是最方便的,不要自己去费时间地写了:

String md5 = DigestUtils.md5Hex("abcdefg");
System.out.println(md5);

结果:7ac66c0f148de9519b8bd264312c4d64

 Maven下载回来的依赖jar包的默认路径
一个Java项目用Maven编译的话,会自动下载回来依赖的jar包,这些jar包如果不在当前路径下,可能在哪里呢?
如果你没配置过的话,应该是在默认路径下:
/home/you_user/.m2/
到这个隐藏路径下搜索那些jar包吧。

 Class.forName 和 ClassLoader.loadClass的区别
这两个方法都可以动态地加载一个类。
之所以要“动态”地加载,是因为有时我们无法预先知道要加载的类是什么,例如,某文件中写了一个类名com.codelast.MyClassA,在读取这个文件之后,我才知道要加载的是类MyClassA,因此,我无法在程序中写诸如 MyClassA a = new MyClassA(); 这样的代码来创建一个类MyClassA的对象,因能“动态”地加载类MyClassA,然后创建一个对象。
但是,这两种加载类的方法的区别是什么呢?
区别在于:Class.forName除了加载类到JVM中,还会执行类的静态初始化;而ClassLoader.loadClass不会执行类的初始化,只是在类被第一次使用时才会进行类的初始化。

 一个Linux文件的toURI()和toURL()的结果有什么不同
如下代码:

File f = new File("/opt/python3.3/bin/python3.3");
System.out.println(f.toURI());
System.out.println(f.toURI().toURL());

输出结果为:

file:/opt/python3.3/bin/python3.3
file:/opt/python3.3/bin/python3.3

可见没有不同。

 为什么要用URLClassLoader来加载类
在某些代码中,会看到用URLClassLoader来加载类,这货与用Class.forName加载类有何区别?
URLClassLoader可以从根据指定的路径搜索到的.class文件,或者根据.jar包中的class来加载类。它就不像Class.forName那样要按包名的方式(例如 Class t = Class.forName("java.lang.Thread"))才能加载一个类了。

 IntelliJ的控制台/console 里的中文显示乱码问题
很久很久以前的IntelliJ是没有这个问题的,后来不记得从哪个版本开始有这个问题了:运行单元测试或main方法时,在控制台输出的中文是乱码的。
解决办法:
菜单“Run”→“Configurations”,在对应的类的“VM options”中添加:

-Dfile.encoding=GB2312

会发现乱码问题就解决了。

 用Ant打包文件时,要打包一个目录下的所有文件的表示方法 / 排除指定文件的表示方法
假设你想把一个目录下的所有文件打进一个jar包里,在build.xml中可以这样写:

<jar jarfile="package.jar">
    <fileset dir="." includes="conf/**/*"/>

</jar>

这样就会把当前目录下的“conf”目录下的目录(包括子目录)和文件打进jar包中。
如果要把conf目录下的一个特定文件 log4j.properties 排除掉(不打进jar包里)呢?可以这样:

<jar jarfile="package.jar">
    <fileset dir="." includes="conf/**/*">
        <exclude name="conf/log4j.*"/>
    </fileset>

</jar>

其中,exclude 就是用来排除的,这里把所有符合 log4j.* 这个pattern的文件都排除掉了。
文章来源:http://www.codelast.com/
 IntelliJ IDEA 13.1不支持subversion 1.8的问题
Ubuntu 14.04用apt-get install安装上的svn已经是1.8.8的版本,如果你没有做过特殊设置,并且使用IntelliJ IDEA中的subversion相关功能(例如compare with latest repository version),会发现提示错误:

Error:svn: E155021: This client is too old to work with the working copy at '/home/codelast/xxx' (format '31').

解决这个问题并不需要重新安装低版本的subversion(那样实在太二了),而是在IntelliJ中设置一下就好了:
Settings→Version Control→Subversion→勾选上“Use command line client: svn”
这样就会告诉IntelliJ使用命令行客户端svn(也就是你安装的subversion 1.8.x)来执行subversion相关功能,这样就没有任何问题了。

 如何转换long到byte数组
别折腾了,直接用Google Guava库中的方法来转,一句话就可以解决:

byte[] converted = Longs.toByteArray(123L);

简单得不能更简单了。

 求两个Set的交集
Google Guava库,这个问题就变得无比简单了:

Set<Integer> set1 = Sets.newHashSet(123);
Set<Integer> set2 = Sets.newHashSet(234);
Set<Integer> intersectedSet = Sets.intersection(set1, set2);
System.out.println(intersectedSet);

输出:

[2, 3]

 启动Zookeeper时指定配置文件
只需要简单地使用 bin 目录下的 zkServer.sh 脚本就可以了:

./zkServer.sh start ../conf/zoo.cfg

这表示用上一级目录下的 conf 目录下的 zoo.cfg 文件作为配置文件来启动Zookeeper。
文章来源:http://www.codelast.com/
 如何让IntelliJ识别JSP代码里的request
如果你发现用IntelliJ idea无法识别JSP代码中的request对象(因此也就无法识别其方法),例如:

String id = request.getParameter("oneId");

这个request对象是HttpServletRequest类的实例,它实现了ServletRequest接口。确实,就算IntelliJ不能识别它,你可以把这个JSP文件部署到Tomcat中让它正确运行,但是写代码的时候多难受啊!其实,你只需要下载一个javax.servlet的jar包,添加到IntelliJ的项目的lib中,就可以了,例如javax.servlet-3.0.jar

 ant test如何单独运行一个UT class?
在一个Java工程下,ant test命令会运行全部的test case,但是如果我们只想运行一个UT class的话,可以这样:

ant test -Dtestcase=MyTest

这就会单独运行MyTest这个类名的UT。

 Maven编译时跳过单元测试

mvn clean install -DskipTests

注意大小写。

 JDK8下的ScriptEngine返回 null 的问题
如果你在Java中执行JavaScript脚本/代码,那么你可能会写类似于下面的代码:

ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
ScriptEngine engine = scriptEngineMgr.getEngineByName("JavaScript");

这些代码在JDK6下运行得很好,但是在JDK8下,你就会发现 engine 变量为null。
首先,从JDK6升级到JDK8,engine name已经不是“JavaScript”而是“nashorn”了,其次,上面的代码还要做一些修改,如下:

ScriptEngine engine = new ScriptEngineManager(null).getEngineByName("nashorn");

具体请看这个链接。
这样修改之后就OK了。

 Zookeeper客户端脚本zkCli.sh删除Zookeeper中一个节点(node)的方法
旧版的zkCli.sh只能删除里面没有下级node的节点,用下面的方法:

[zk: zk.codelast.com:2191(CONNECTED) 1] delete node_to_del

如果node_to_del下面还有其他节点(即非空),会提示一个错误,说里面非空,不允许删除。要递归删除,只能自己写个程序了。
文章来源:http://www.codelast.com/
而新版的zkCli.sh可以删除里面非空的节点,用下面的方法:

[zk: zk.codelast.com:2191(CONNECTED) 1] rmr node_to_del

其中,node_to_del节点里面可以非空。

 IntelliJ IDEA里,一个项目的所有外部依赖包都无法识别(全部红色),怎么办?
这是一个非常恼人的问题,我在网上搜了很多办法都没用,包括清除缓存,重新import maven项目,等等,能用的招都试了一遍,但是对自己电脑上的某些特定项目,它就是有这个问题。IntelliJ IDEA的论坛里那些讨论帖子里也有很多人反映一样的问题。
最后,是添加了一个 ~/.m2/settings.xml 文件,在里面添加了某些内容之后治好的,其中有一段关键的代码是:

    <mirror>
      <id>maven-central</id>
      <mirrorOf>central</mirrorOf>
      <url>http://xxx.codelast.com/repositories/releases</url>
    </mirror>

其中,上面的“url”字段要视情况改成适合你用的。

 对一个list中的元素排序,排序依据是元素对象的一个double字段(从大到小)

@Test
public void test() throws Exception {
  // 测试对一个list中的元素排序,排序依据是元素对象的一个double字段(从小到大)
  CustomObject object1 = new CustomObject().setField(2.0);
  CustomObject object2 = new CustomObject().setField(1.0);
  CustomObject object3 = new CustomObject().setField(3.0);

  List<CustomObject> list = Lists.newArrayList(object1, object2, object3);
  list.sort(Comparator.comparingDouble(CustomObject::getField));
  //Collections.reverse(list);  // 如果需要的话,再把排好序的list逆序
  for (CustomObject object : list) {
    System.out.println(object.getField());
  }
}

@Data
@Accessors(chain = true)
private static class CustomObject {
  private double field;
}

输出:

1.0
2.0
3.0

上面的代码是在UT中写的,CustomObject的两个annotation:@Data 和 @Accessors(chain = true) 都来自于 lombok 库。

文章来源:https://www.codelast.com/
➤➤ 版权声明 ➤➤ 
转载需注明出处:codelast.com 
感谢关注我的微信公众号(微信扫一扫):

wechat qrcode of codelast
 

发表评论