java代码技巧

修改不可改变的String

利用反射来修改不可变的字符串

public class BreakImmutable {
    public static void main(String[] args) throws Exception {
        String name = "aaa";
        change(name);
        System.out.println(name);//打破String不可变之后,这里会打印bbb
    }

    public static void change(String name) throws Exception {
        //利用反射获取String中的value数组
        Class<?> clazz = Class.forName("java.lang.String");
        Field field = clazz.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(name);

        //直接修改value数组中的值
        for (int i = 0; i < value.length ; i++) {
            value[i] = 'b';
        }
    }
}

修改Integer缓存池范围

Integer中维护了一个数组,有的地方称之为Integer缓存池,当值在[-128,127]之间的话,会利用这个数组,比如下面代码的结果是true

Integer i1 = 66;
Integer i2 = 66;
System.out.println(i1 == i2);

这个数组的范围是可以利用参数来修改的:

-XX:AutoBoxCacheMax=256

输入上面参数之后,数组上限变成了256

指定睡眠时间

当我希望睡一天

Thread.sleep(算一算);//一天是多少毫秒来着?

使用juc包下的类:

TimeUnit.DAYS.sleep(1);//轻松

防止空指针

下面代码当a为null的时候,会出现空指针

if(a.equals(b))

使用Objects来判断可以防止空指针的出现

Objects.equals(a,b);

数组转集合

将数组转成集合之后,再向集合中添加数据

//数组转集合
Integer[] arr = {9, 5, 2, 7};
List<Integer> list = Arrays.asList(arr);
//向list中添加一个数字
list.add(8);

上面代码再运行之后会报UnsupportedOperationException的异常,原因是这里获取的list对象是Arrays类中的静态内部类ArrayList并非java.util.ArrayList,可以通过下面写法来解决这个问题:

//数组转集合
Integer[] arr = {9, 5, 2, 7};
List<Integer> list = Arrays.asList(arr);

ArrayList<Integer> arrayList = new ArrayList<>(list);
//向list中添加一个数字
arrayList.add(8);

ForkJoinPool的误用

比如下面代码我要用ForkJoin对范围内的整数求和,需要注意的是不要调用这个fork方法,这样不能充分利用线程池中的线程。

public class CountTask extends RecursiveTask<Long> {

    //任务分解的阈值
    private int threshold = 5;
    private long begin;
    private long end;

    public CountTask(long begin, long end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long sum = 0;
        if (end - begin <= threshold) {
            for (long i = begin; i <= end; i++) {
                sum += i;
            }
        } else {
            long middle = (begin + end) / 2;

            //分解任务
            CountTask leftTask = new CountTask(begin, middle);
            CountTask rightTask = new CountTask(middle + 1, end);

            //执行任务
            invokeAll(leftTask,rightTask);
            
            /*
            	调用上面的invokeAll方法即可
            	不要再调用这两个fork方法了
            */
            //leftTask.fork();
            //rightTask.fork();

            //获得计算结果
            Long leftResult = leftTask.join();
            Long rightResult = rightTask.join();
            //将结果求和
            sum = leftResult + rightResult;

        }
        return sum;
    }
}