java基础知识

来源:互联网 发布:js右键后弹出菜单 编辑:程序博客网 时间:2024/06/03 21:46

java基础知识

 1、java -D参数
在一个类A中,有语句:System.getProperty("param1");
在运行该类时,可以通过-D来设置param1的值,如下:
java -Dparam1=value1 A
还可以设置多个,用空格隔开:
java -Dparam1=value1 -Dparam2=value2 A

jvm参数查询:http://blogs.oracle.com/watt/resource/jvm-options-list.html

2、jdk的DateFormat、SimpleDateFormat、DecimalFormat,不是线程安全的。在需要使用的时候,应该new一个实例来使用。

3、通过Runtime,获取运行过程中,内存的使用情况:
Runtime rt = Runtime.getRuntime();
long totalMem = rt.totalMemory();
long freeMem = rt.freeMemory();

4、小心java可变参数

    public static void test(Long... longs) {        if (longs == null) {            System.out.println("null");        } else {            System.out.println(longs.length);        }    }    public static void main(String args[]) {        Long id = null;        test(id); // 输出:1        test(null);// 输出:null        test(id, null);// 输出:2        test(null, id);// 输出:2        test(null, null);// 输出:2    }

5、serializable

    把一个Java对象序列化之后,所得到的字节数组一般会保存在磁盘或数据库之中。在保存完成之后,有可能原来的Java类有了更新,比如添加了额外的域。这个时候从兼容性的角度出发,要求仍然能够读取旧版本的序列化数据。在读取的过程中,当ObjectInputStream发现一个对象的定义的时候,会尝试在当前JVM中查找其Java类定义。这个查找过程不能仅根据Java类的全名来判断,因为当前JVM中可能存在名称相同,但是含义完全不同的Java 类。这个对应关系是通过一个全局惟一标识符serialVersionUID来实现的。通过在实现了Serializable接口的类中定义该域,就声明了该Java类的一个惟一的序列化版本号。JVM会比对从字节数组中得出的类的版本号,与JVM中查找到的类的版本号是否一致,来决定两个类是否是兼容的。对于开发人员来说,需要记得的就是在实现了Serializable接口的类中定义这样的一个域,并在版本更新过程中保持该值不变。当然,如果不希望维持这种向后兼容性,换一个版本号即可。该域的值一般是综合Java类的各个特性而计算出来的一个哈希值,可以通过Java提供的serialver命令来生成。在Eclipse中,如果Java类实现了Serializable接口,Eclipse会提示并帮你生成这个serialVersionUID。

    在类版本更新的过程中,某些操作会破坏向后兼容性。如果希望维持这种向后兼容性,就需要格外的注意。一般来说,在新的版本中添加东西不会产生什么问题,而去掉一些域则是不行的。

    通过网络传输的对象(例如接口上的参数、返回值类型、会抛出的异常类),必须实现Serializable接口,或者父类已经实现序列化接口。ArrayList.subList()返回的List实现类是内部类型,不能序列化的,通过网络传输会出错。网络传输对象要有无参构造器,因为机器系统是不知道传什么内容给有参构造器进行实例化,无参构造器不是public都没关系。

    网络传输最好不要用enum类型,太强耦合,从网络一端传到另一端,对方可能还是旧版本而识别不了。看看HashMap、Date的源代码,不需通过网络传输的field用transient定义,然后实现writeObject等方法。不要序列化大数据对象/十分复杂对象,一般long/int/String/Map/List/Array等常见类组成的对象就已能解决问题,最好不要在本应用的业务接口传递/返回另一人主导业务/结构的对象。

    网络对象第一次上线使用时,就要设定serialVersionUID,不要不顾编译警告。如果没有显式赋值,也在你看不见觉察不到的情况下,在你增减了field/修改了定义的情况下,serialVersionUID已被改变,这时网络两端就对接不上而悲剧了。

    由于没赋值serialVersionUID 只是警告,不是错误,造成先前没留意设定serialVersionUID,网络两端上线运行一段时间也感觉正常。 如果再增减修改field,没赋值好serialVersionUID,网络两端就不匹配。

解决步骤如下:serialver命令在jdk/bin目录,用于算出某类的serialVersionUID。

(1)用旧代码的类生成 serialVersionUID: serialver -classpath myjar-1.0.jar com.taobao.myjar.MyDO

输出结果类似:com.taobao.myjar.MyDO: static final long serialVersionUID = 2075130392266935898L;

(2)然后将这行代码复制到新代码上。

6、new Integer和Integer.valueOf()

Integer m = new Integer(10) 
Integer n = Integer.valueOf(10); 
两个都是得到一个Integer对象,
要注意的是,new Integer返回的永远是不同的对象,但是当整数范围在-128<=i<=127时,Integer.valueOf返回的是同一个对象。因为Integer.valueOf用到了缓存,所以效率高。
实际上,在我们用Integer a = 数字;来赋值的时候Integer这个类是调用的public static Integer valueOf(int i)这个方法。
Integer a = 10;
Integer b = 10;
System.out.println(a == b)
输出结果为true

7、如何查看一个程序启动之后,加载了哪些类
方法一:使用java命令启动程序的时候,加上参数“-verbose”,来查看系统类的装载信息。格式如:java -verbose myAppName
              程序启动之后,可以看到系统加载了哪些类,并且从哪个jar文件中加载的这个类
方法二:程序启动之后,使用jmap dump进程的堆栈信息,然后使用MAT进行分析。