Java你不知道的那些事儿—Java隐藏特性

转载自:http://www.cnblogs.com/lanxuezaipiao/p/3460373.html

每 种语言都很强大,不管你是像我一样的初学者还是有过N年项目经验的大神,总会有你不知道的东西。就其语言本身而言,比如Java,也许你用Java开发了 好几年,对其可以说是烂熟于心,但你能保证Java所有的用法你都知道吗?今天没事就来整理下Java中有哪些隐藏的特性呢?知道的可以举手哦~~~

一、双括号初始化语法(DoubleBraceInitialization)(这里指的是大括号{})

主要指的是集合类(List,Map,Set等),我们创建一个常量集合或传递一个常量集合作为参数,往往都会这么做(以Set为例):

 Set<String> validCodes = new HashSet<String>();
 validCodes.add("XZ13s");
 validCodes.add("AB21/X");
 validCodes.add("YYLEX");
 validCodes.add("AR2D");
 removeProductsWithCodeIn(validCodes);

或在类中初始化一个常量集合:

 private static final Set<String> VALID_CODES = new HashSet<String>();
 static {
    validCodes.add("XZ13s");
    validCodes.add("AB21/X");
    validCodes.add("YYLEX");
    validCodes.add("AR2D");
 }

会不会觉得每次都这样很费时费力,其实,有更好的办法,那就是双括号语法,像下面这样:

 private static final Set<String> VALID_CODES = new  HashSet<String>() {{
    add("XZ13s");
    add("AB21/X");
    add("YYLEX");
    add("AR2D");
 }};

// Or:

 removeProductsWithCodeIn(new HashSet<String>() {{
    add("XZ13s");
    add("AB21/X");
    add("YYLEX");
    add("AR5E");
 }});

这里解释下这两个括号:第一个括号创建了一个新的匿名内部类,相信这个大家都知道;第二个括号声明了匿名内部类实例化时运行的实例初始化块。

使用双括号语法需要注意两点:

1. 如果要在匿名内部类中要建立匿名子类,那么只能用于非final的类,这很明显,且不仅局限于集合类,可以用来实例化任何对象,例如用于GUI对象,如下:

 add(new JPanel() {{
    setLayout(...);
    setBorder(...);
    add(new JLabel(...));
    add(new JSpinner(...));
 }});

2. 这种语法与常用的equals(Object o)方法不兼容。例如Example类有这样的方法:

 public boolean equals(final Object o) {
    if (o == null) {
        return false;
    } else if (!getClass().equals(o.getClass())) {
        return false;
    } else {
        Example other = (Example) o;
        // Compare this to other.
    }
  }

那么,使用双括号初始化语法创建的任何对象都不会与未使用双括号语法创建的对象相等。因此,建议大家:如果类中需要equals(Object o)方法,那就老老实实不要使用这种语法了。不过集合类没有这种问题,应该是因为集合内部优化了的原因。

那么什么时候建议大家使用双括号语法呢?

如果你只是要创建并初始化一个实例而不是创建一个新类,或者创建任何不添加字段属性或重载方法的匿名类时,用双括号语法就很nice了。

3. 如果你用的是集合类且该类有构造器参数接受另一个集合生成该集合的实例,那么有个更好的更惯用的替代方法,如大家都知道的List初始化可以用Arrays.asList(),如下:

List<String> myList = new ArrayList<String>(Arrays.asList("One", "Two", "Three"));

但需要注意:asList返回的是一个长度不可变的列表。数组是多长,转换成的列表是多长,我们是无法通过add、remove来增加或者减少其长度的。

二、类型参数的与操作&(TypeParameterJointUnion

就是参数绑定多个类型,如:

public class ClassName<T extends Class & Interface1 & Interface2 & ...> {}

注意:这里extends后面只有第一个为类Class,后面&的全部都是接口Interface,而且类Class的声明或定义必须在Interface之前。

举个例子:如果你想要一个既是 Comparable类又是Collection类的参数,实现的功能是:两个给定的集合是否相等或两个集合中的任一个是否包含指定的元素,那么你可以用下面的函数实现:

public static <A, B extends Collection<A> & Comparable<B>> boolean foo(B b1, B b2, A a) {
    return (b1.compareTo(b2) == 0) || b1.contains(a) || b2.contains(a);
}

这里b1和b2可以同时具有类型Collection和Comparable类型,因此可以使用Collection类的contains方法也可以使用Comparable类的compareTo方法。

三、VisualVM监控工具(Java VisualVM

这是JDK6.0 update 7 中自带的监控工具(java启动时不需要特定参数,该工具在bin/jvisualvm.exe),能够监控线程,内存情况,查看方法的CPU时间和内存 中的对象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的)。

双击打开,从UI上来看,这个软件是基于NetBeans开发的了。

从界面上看还是比较简洁的,左边是树形结构,自动显示当前本机所运行的Java程序,还可以添加远程的Java VM,其中括号里面的PID指的是进程ID。OverView界面显示VM启动参数以及该VM对应的一些属性。Monitor界面则是监控Java堆大 小,Permgen大小,Classes和线程数量。Profiler界面比较有趣,看样子似乎可以动态的对某个Java程序进行调优了。不过我没试用这 个功能,感觉要调优还是在Netbeans里面比较自然一点,起码有代码,没代码调优了用处也不大。

四、Classpath支持通配符(Setting the class path

这是Java 6开始支持的功能,比如在工程中经常会有这样的配置:

java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main

比较复杂,还容易出错,其实可以用通配符更加简洁方便:

java -classpath ./lib/* so.Main

五、协变返回类型( covariant return types

这是Java 5添加的功能,在Java5之前我们在子类中覆盖基类的方法时是不能改变被覆盖方法的返回类型的,就是基类和父类的方法必须一模一样,想要改变只能在创建 对象时Cast。Java 5过后,我们就可以改变了,不过需要注意的是:改变后的类型必须是原类型的子类型。举个例子就一目了然了。

public class CovariantReturnTypesTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Mill m = new Mill();
        Grain g = m.process();
        System.out.println(g);  // output: Grain
        m = new WheatMill();
        g = m.process();
        System.out.println(g); // output: Wheat
    }

}

class Grain {
    public String toString() {
        return "Grain";
    }
}

class Wheat extends Grain {
    public String toString() {
        return "Wheat";
    }
}

class Mill {
    Grain process() {
        return new Grain();
    }
}

class WheatMill extends Mill {
    // 这里返回类型改为了Grain的子类型Wheat
    Wheat process() {
        return new Wheat();
    }
}

参考自:Hidden Features of Java

时间: 2024-11-05 02:35:43

Java你不知道的那些事儿—Java隐藏特性的相关文章

java基础 第5章 隐藏实施过程

第5章 隐藏实施过程 "进行面向对象的设计时,一项基本的考虑是:如何将发生变化的东西与保持不变的东西分隔开." 这一点对于库来说是特别重要的.那个库的用户(客户程序员)必须能依赖自己使用的那一部分,并知道一旦新版本的库出台,自己不需要改写代码.而与此相反,库的创建者必须能自由地进行修改与改进,同时保证客户程序员代码不会受到那些变动的影响. 为达到这个目的,需遵守一定的约定或规则.例如,库程序员在修改库内的一个类时,必须保证不删除已有的方法,因为那样做会造成客户程序员代码出现断点.然而,

Java面向基础概述和三大特性

Java 是面向对象的高级编程语言,类和对象是 Java 程序的构成核心.围绕着 Java 类和 Java 对象,有三大基本特性:封装是 Java 类的编写规范.继承是类与类之间联系的一种形式.而多态为系统组件或模块之间解耦提供了解决方案. 本文主要围绕这三大特性介绍一下 Java 面向对象.组件解耦的核心思想. 1.面向对象思想 面向对象编程是当今主流的程序设计思想,已经取代了过程化程序开发技术,Java 是完全面向对象编程语言,所以必须熟悉面向对象才能够编写 Java 程序. 面向对象的程序

java 1.7 1.8新特性

在JDK1.7的新特性方面主要有下面几方面的增强:1.jdk7语法上1.1二进制变量的表示,支持将整数类型用二进制来表示,用0b开头.1.2 Switch语句支持string类型1.3 Try-with-resource语句 注意:实现java.lang.AutoCloseable接口的资源都可以放到try中,跟final里面的关闭资源类似: 按照声明逆序关闭资源 ;Try块抛出的异常通过Throwable.getSuppressed获取1.4 Catch多个异常 说明:Catch异常类型为fi

用Java来比较JavaScript的一些特性

由于是从java做到JavaScript,所以对强弱语言类型,还是比较敏感的.JavaScript是弱语言,只严格区分数据和指令.简单描述下自己对两者之间的一些区别吧. 1.JavaScript变量的类型取决于右侧的对象. JavaScript: var variable_name = new Object(); Java: Object variable_name = new Object(); 2.JavaScript没有块级作用域, Java: if(true) { Object a =

Java入门——深入理解Java三大特性

Java入门——深入理解Java三大特性 本Blog内容: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法(getter,setter),如果不想被外界方法,我们大可不必提供方法给外界访问. 封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码. 可以对成员变量进行更精确的控制.(在setter方法中进行实际意义的校验) 总结:控制属性访问权限,不是你想改就能改.容易修改属性类型.精确控制属性的取值范围. 继承 继承是使用已存在的类

Java进阶--Chapter 1 Java的跨平台特性的原理

Java的 跨平台特性和为什么Java要拥有这个特性 注:相关内容摘自网络,忘记出处,故未注明,若有不妥忘其告知,加以改正: 有过基础Java知识的开发人员都知道Java是跨平台的,可我们知道Java为什么要跨平台吗,Java的跨平台又是如何实现的呢?下面我们来一一了解. 什么是平台 Java是可以跨平台的编程语言,那我们首先得知道什么是平台,我们把CPU处理器与操作系统的整体叫平台. CPU大家都知道,如果计算机是人,那CPU就是人的大脑,它既负责思维运算,又负责身体各部件的命令控制.CPU的

Java 8的八个新特性

Java 8的八个新特性 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 1.接口的默认方法和静态方法 Java 8在接口方面引入了新特性. Java 8版之前,接口只有抽象方法,而在Java 8,为接口新增了两种类型的方法. 第一种是默认方法.此方法使用了default关键字修饰方法名.实际上接口不包含任何实现的方法,而在Java 8中,可以通过使用default关键字来添加默认的方法实现. 接口的实现类可以直接使

你可能没听过的 Java 8 中的 10 个特性

你以前听到的谈论关于Java8的所有都是围绕lambda表达式. 但它仅仅是Java8的一部分. Java 8 有许多新特性---一些强大的新类和语法, 还有其他的从一开始就应该具有的东西. 我将要介绍我认为值得了解的10个精华特性. 它们中最少也会有一个或两个你想要试一试, 所以我们开始吧! 1. 默认方法 Java语言一个新添加的特性是你可以为接口(interface)的方法添加方法体(称为默认方法). 这些方法会被隐式地添加到实现这个接口的类中. 这能使你在不破坏代码的情况下为已存在的库添

java线程:单例隐藏ThreadLocal实现线程数据共享

问题: 给定的二叉查找树中,有两个节点不小心被调换了位置,现在需要将其修正,不改变树的结构. 分析: 二叉排序树的中序遍历是有序的,所以这个问题又是建立在中序遍历模板上的问题,所以我们可以对其进行中序遍历,并用一个pre指针指向当前遍历结果中的最后一个结点,即下次遍历前的前一个结点.然后就可以通过将当前结点与pre结点进行比较,来判断是否有序了.若乱序,就将这两个结点都放入到预先定义的容器中. 错误的形式就这两种,我们看到,在乱序容器中,最多就存了四个元素,所以空间复杂度还是满足O(n)的,当然