java 泛型 四则_一些比较冷门但非常实用的java技巧

Java有很多十分有用但不太为人知道的语法,在这里向大家介绍一些( `ー´)ノ

只要稍微学过JavaSE便可以轻松读懂本文内容,并且在实战用派上用场——

1.基础

写一个内部类

通过生成一个和外部类的实例保持关联的实例,使得外部类的实例与内部类的实例之间,能够保持一种【类-实例】似的关系

public class Outer {

public class Inner {

}

}

如上写了一个内部类的话,可以像下面一样生成实例

Outer o = new Outer();

Inner i = o.new Inner();

在new内部类的实例之前,先生成一个外部类的实例

虽然如果用this代替o来传值的话,就要写成this.new这样的形式,但是this.是可以被省略的,所以用Outer类的方法来new一个Inner类的实例的情况,可以省略this.new,单纯用new Inner()就行

public class Outer {

public class Inner {

public class Inner2 {

public class Inner3 {

}

}

}

public void echo() {

Inner i = new Inner(); //省略this.new直接写newInner.Inner2 i2 = i.new Inner2();

Inner.Inner2.Inner3 i3 = i2.new Inner3();

}

}

当然了,多层生成也是非常实用的 (连续用.连接的感觉很爽吧)

new Outer().new Inner().new Inner2().new Inner3();

不写main方法来执行程序

因为在main方法被调用之前,class会先被初始化,在那个过程之中写入代码的话,就能够实现没有main方法的情况下执行程序

public class Starter {

static {

System.out.println("Hello!");

}

}

在这个例子中使用了最传统的锁定static初始化方式

这也是short coding或者code golf的选手最常用的手法之一,在命令行中我们可以如下一样执行:

C:\hoge>java Starter

Hello!

Exception in thread "main" java.lang.NoSuchMethodError: main

Hello!被输出在初始化类的阶段,在那之后的NoSuchMethodError中被提示不存在main方法

我们还能如下一样调用static的方法来执行程序

public class Starter {

static int i = echo();

private static int echo() {

System.out.println("Hello!");

return 0;

}

}

System.out.println方法

System.out可以用System.setOut()方法来替换

写一个继承java.io.PrintStream的类再稍微调整一下的话,就能愉快地使用System.out.println()啦!(比如添加一个有趣的语尾)

注释

我们都知道可以用//来注释一行内容。通过在注释中放置unicode-escape过的换行符,可以让代码伪装在注释中

比如下面这段代码:

public class Test {

public static void main(String[] args) {

int i = 5;

// #start unsafe# http://java.sun.com\u000a\u002f\u002a int *ip = &i;

*ip += 3;

i = *ip;

// #end unsafe# http://java.sun.com\u002a\u002fi+=\u0033\u003b System.out.println(i);

}

}

声明

变量的声明可以用过注解来实现。首先,我们在@Target里写上包含LOCAL_VARIABLE的注解

import java.lang.annotation.Target;

import java.lang.annotation.ElementType;

@Target(ElementType.LOCAL_VARIABLE)

public @interface Echo {

}

这样的话,我们就能在注解中声明变量啦 *1

@Echo Echo Echo = Echo();

其次,我们可以通过使用transient关键字和volatile关键字,来吓一吓不是很熟悉语法的人

不过用泛型的效果会更加好一些

public class Echo {

Echo Echo;

}

注意,这里的Echo并不是Echo型的,而是Echo泛型变量~

编译程序

java的命令有几个增添的option

如果在option中使用-g:none,那么debug的信息便不会被输出,stacktrace中的行号也会被变成unknown

而option里的-processor是关联着注解处理的

执行程序

同样地,在执行命令中也有几个很方便的option

例如-D可以调试系统属性,推荐改写path.separator

-javaagent也是有趣的一个option

2.数字

数字的表现

在java的数字表现中,8进制是比较推荐使用的

System.out.println(012);

结果:

10

没有使用特别的符号,因此比较被难以察觉,能够让读代码的人多思考代码的含义

四则运算

希望记住的是Double.NaN

这是double类型的其中一种,作用是声明不是一种数字,在0.0/0.0这样的运算中发生

同样地,NaN和其他的值产生的运算结果也是NaN,在处理过程中添加NaN的话,便可以避开复杂的运算得到人为可见的结果

同时,NaN==NaN的情况下,结果是false也是一个需要注意的地方,在某个Java问答中,有人就是利用了这个特性出了下面这个题目:问题29:循环大佬的花嫁(Bride of Looper)

请将下列循环通过声明i变成无限循环

while(i != i) {

}

增值和减值操作符

下列代码可能招致完型崩坏(semantic satiation)

int i = 0;

i = i++ + ++i;

System.out.println(i);

3.字符串

字符串和Object之间的加号会自动运用对象的toString方法

在Eclipse这些IDE的Debuger中确认变量的值的时候,也是用这个,因此适当地随便override一下会让debug更能沉淀时间

4.数组

在Java5之后使用数组的机会少了很多,但是依然存在着用可变长参数的机会

public class Hoe {

private Class type;

public Hoe(E... e) {

@SuppressWarnings("unchecked")

Class type = (Class) e.getClass().getComponentType();

this.type = type;

}

public Class getType() {

return type;

}

}

这样的话,便能获得到具体的泛型

比如:

Hoe hoe = new Hoe();

之中,hoe.getType()便是Fuga.class(好用吧)

这个方法是通过在构造器中放置一个长度可变的参数,在调用new Hoe()的时候传递一个大小位0的Fuga[]给构造器,再从那之中获得具体的泛型类型

5.哈希

稍微修改Object#hashCode()和Object#equals可以让标准API的java.util.HashMap产生一些奇妙反应

java.lang.Comparable或者java.util.Comparator中,如果使得不等价的对象返回0时,可以消灭java.util.TreeMap的put进去的对象

6.控制

if

通过在条件式中运用逻辑互斥或^(XOR)来让代码更加有高级感

if (a == null ^ b == null) {

throw new NullPointerException();

}

for

在控制中知名度比较低的应该属于标签(label)了吧?在for和while之中我们都会使用break和countinue,但是在多重循环中,我们应该学会控制某个单独的循环

yLoop: for (int y=0; y

xLoop: for (int x=0; x

if (map[x][y] == Type.BOMB) {

break yLoop;

}

}

}

正好可以通过标签+注释的方式,让代码看着像URL,有整洁感

http://example.jp/for (int i=0; i

}

break并不是只能在循环体中使用:

hoge: {

piyo: {

break hoge;

}

}

7.方法

多使用strictfp关键字

用synchronized关键字的话比较土避开比较好

8.异常处理

在finally之中用return和throw之类提高速度的关键字

9.反射

通过java.lang.reflect包,可以参照动态的变量以及调用动态的方法

setAccessible方法甚至可以在外部调用private方法

10.类加载器

通过自己写一个类加载器,可以在执行时更换类的内容

例如defineClass方法可以从byte数组中生成类,重写这个方法可以给byte数组里面加一些料

*1: 通常,Java的命名规范里变量通常是小写字母开始,在这里故意写成大写的,便能实现注释/类型/变量名/构造器名四个Echo拥有各自的功能

*2 Java5以后的泛型比起数组更常用List接口,长度可变的形参传递依然是在数组中实现所以用起来很麻烦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值