伪代码:
public class testTransactional { @Transactional public void methodA(String id) { g4Dao.update(id); methodB(id); } public void methodB(String id){ Boolean result = g4Dao.insert(id); if (!result) { throw new Exception("我要抛异常"); } } }
正常来说,methodA被@Transactional标注,那么里面的 *** 作应该在一个事务中进行。
但是,如果methodB *** 作失败,抛出异常,methoA的update *** 作没有回滚,这是什么原因呢?
@Transactional注解默认情况下只有遇到Uncheck Exception才会回滚,对于Check Exception不会进行任何 *** 作。
解决方案:
1.可以抛出Uncheck Exception。
throw new RuntimeException("我要抛异常");
2.在注解@Transactional配置回滚异常
@Transactional(rollbackFor = Exception.class)
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd"); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR,2019); //月份从0开始 calendar.set(Calendar.MONTH,11); calendar.set(Calendar.DAY_OF_MONTH,29); System.out.println("Date: 2019.12.29转换String" + sdf.format(calendar.getTime()));
期望输出2019-12-29,但是输出结果却是:
原因:
SimpleDateFormate在表示年份的时候存在两种格式,一种是大写的YYYY,一种是小写的yyyy。这两种格式表达的含义是不一样的。YYYY表示的是"周年",也就是这一周所在的年份。yyyy表示的这一天所在的年份。
获取一个0到25随机数的功能:
public static Integer randomNumber() { Random random = new Random(1000); return random.nextInt(26); }
执行可以发现,每次获取的随机数都一样。
原因:
每次获取随机数,都会创建一个新的Random对象。Random是基于Seed值产生一个伪随机序列。由于新的Random对象的Seed都一样,随机的算法一样,导致生成的随机数一样。
可以将随机对象Random定义为类对象。避免这个问题。如:
static Random random = new Random(); public static Integer randomNumber() { return random.nextInt(26); }4.三元表达式,抛出空指针异常
public Integer compareAndSum(Integer number1,Integet number2,Integer defaultNumber) { return number1 > number2 ? number1 + number2:defaultNumber; }
如果number1 小于 number2的时候,就会抛出空指针异常。
原因:
number1 + number2,会被转换为基础类型。所以对defaultNumber进行转换的时候,机会抛出空指针异常。
如果使用三元表达式,我们要确认会不会存在参数为null的情况。如果存在,就需要用if…else…代替。
我们知道在Java Web中,每一次用户请求都会从容器的线程池取一个新的线程来负责执行请求。在这个线程中,我们经常使用ThreadLocal来存储上下文信息,这样,就可以在线程的整个声明周期里都可以取用这个应用上下文信息。
但是,在使用ThreadLocal对象的时候,会遇到明明没有设置值却可以从中取到数据的现象。
原因:
因为线程我们是从线程池中取出来的,两次请求完全有可能是使用的同一个线程。如果第一个请求使用完后,没有清除ThreadLocal,那么这个线程的ThreadLocal对象还是会存在上下文信息。
所以,我们要记住每次使用线程后,把ThreadLocal对象清除掉就可以了。
如果定义一个HashMap,key为自己定义的类。如果这个类没有重写hashcode,equals方法,会出现什么问题?
public class TestKey { private String id; public TestKey(String id) { this.id = id; } }
public class Test { public static void main(String[] args) { HashMap map = new HashMap<>(); TestKey key1 =new TestKey("10"); TestKey key2 =new TestKey("10"); map.put(key1,"hello world"); System.out.println(map.get(key2)); }
我们期望通过key2也可以获取到hello world字符串。但是结果却是:
原因:
因为存入map,如果没有重写hashcode方法,默认调用Object的hashcode方法,得到的是对象的内存地址。key1,key2是两个对象,所以取不到值。
如果TestKey重写hashcode方法,不重写equals方法,行不行呢?
答案还是不行,如果重写hashcode方法,可以让map的key一样,但是通过equals比对的时候,调用的还是Object的equasl方法,比对的还是内存地址。
所以说,要重写hashcode和equals方法。才行。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)