SQL中灵活使用ASCII码
请你编写一个 SQL 查询来交换所有的 'f' 和 'm' (即,将所有 'f' 变为 'm' ,反之亦然),仅使用 单个 update 语句 ,且不产生中间临时表。
注意,你必须仅使用一条 update 语句,且 不能 使用 select 语句。
解答:
UPDATE Salary SET sex = char(ascii('m') + ascii('f') - ascii(sex));
safeEqual防止Timing Attack
源码:
boolean safeEqual(String a, String b) {
if (a.length() != b.length()) {
return false;
}
int equal = 0;
for (int i = 0; i < a.length(); i++) {
equal |= a.charAt(i) ^ b.charAt(i);
}
return equal == 0;
}
原理解答:
这种手段可以让调用 safeEquals("abcdefg", "fjkmln") (只有首位不相同)和调用 safeEquals("abcdefg","abcdefg") (两个完全相同的字符串)的所耗费的时间一样。防止通过大量的改变输入并通过统计运行时间来暴力破解出要比较的字符串。
提高可测性
案例一
优化前:
该代码由于产生的结果为随机数,导致无法判断结果是否正确无法测试
public int a(){
return RandomGenerator.getDefault().nextInt(1000)+1;
}
优化后:
Supplier是一个java8提供的函数接口,无参数返回值类型为T类型,单元测试可通过传入常量来测试该方法,线上可通过传入()->RandomGenerator.getDefault().nextInt(1000)参数运行该方法
public int a(Supplier<Ingeter> supplier){
return supplier.get()+1;
}
测试代码:
public void testa(){
assert a(()->1) == 2;
}
案例二
优化前:
该代是一个典型的生产者消费传递内容代码,存在异步过程无法进行测试
public <T> void producerConsuer(Consumer<Consumer<T>> producer,Consumer<Supplier<T>> consumer){
BlockingQueue<T> blockQueue = new LinkedBlockingQueue<>();
new Thread(()->producer.accept(blockQueue::add)).start();
new Thread(()->consumer.accept(()->{
try{
return blockQueue.take();
}catch(InterrutedException e){
throw new RuntimeException(e);
}
})).start();
}
优化后:
增加一个jdk本身提供的Executor接口类,该接口类在单元测试时候我们可以传递一个同步状态Executor,线上可传入一个线程Executor运行该方法
public <T> void producerConsumer(Executor executor,
Consumer<Consumer<T>> producer, Consumer<Supplier<T>> consumer){
BlockingQueue<T> blockQueue = new LinkedBlockingQueue<>();
new Thread(()->producer.accept(blockQueue::add)).start();
new Thread(()->consumer.accept(()->{
try{
return blockQueue.take();
}catch(InterrutedException e){
throw new RuntimeException(e);
}
})).start();
}
单元测试用例:
public void producerConsumer(){
producerConsumer(Runnable::run,
Consumer<Consumer<T>> producer->{
producer.accept(1);
producer.accept(2);
},
consumer->{
assert consumer.get() == 1;
assert consumer.get() == 2;
}
);
}