任小龙(Will、龙17)高级讲师
EasyJF开源团队成员,技术经理,高级讲师。
擅长技术:JavaSE、Java Web、Spring、Hibernate、MyBatis、Spring MVC
、Struts2、Struts1、 WebService、Lucene、Android等开源技术;以及Oracle、MySQL等数据库技术。
龙老师实战经验丰富,热衷探索新技术,拥有多年的Java开发和培训经验,
授课富有激情又通俗易懂,知识点分析深入,举例贴近生活不乏幽默生动,注重引导学生思维。
讲课风格:课堂幽默生动,思维行云流水,授课水到渠成。
学生点赞:龙哥的视频,苍老师都喜欢。
Java和Python哪个就业情况更好?
首先,在了解一个语言就业好不好之前,
得先明确语言的发展方向
(1)Python
Python:数据分析,人工智能,web开发,测试,运维,web安全。
(2)Java
Java:web开发,大数据开发,安卓开发,服务器开发, 桌面开发,游戏开
发。
Java作为全球占比**高的开发语言,有着她独一无二的优势,但因竞争太大
,就业方面并不比Python好。
而基于目前国内python人才需求呈大规模上升,薪资水平也水涨船高。学
python的人大多非科班出身。很多大学并没有开始此专业,因此就出现了大量的人才缺口。
从图上可以清晰的判断未来python就业形势,是大幅度上升的,加上互联网
行业正在进入成长爆发期,所以现在开始学习python的小伙伴果然是明智滴。
就业发展
与此同时,目前的互联网行业在高速发展的过程中,对于人工智能,数据分
析在北京、上海、深圳各大互联网发达的一线城市越发的火热,招聘优秀的Python程序员的难度尤为突出,为此选择就业Python更易成功。
Python人气爆棚的秘密
Python之所以排名上的如此之快,和它本身的特点也有关系,他是一种简单
、易用但专业、严谨的通用组合语言,或者叫胶水语言,让普通人也能够很容易的入门,把各种基本程序元件拼装在一起,协调运作。比如任何一个人
,只要愿意学习,可以在几天的时间里学会Python基础部分,然后干很多很多事情,这种投入产出比可能是其他任何语言都无法相比的而且Python的应
用很广,很多行业都会应用。
全新升级企业需求的Java课程
历经16年累计10余万Java学员。打造专业的课程体系,值得你的信赖
Java基础
深入解析Java基础,直击面试常见问题。——184课时
数据库
及Web前端技术
包含主流Oracle和MySQL数据库,先进的Web前端技术,热门的JS语言 ——160课时
Java Web
开发及服务端框架
定制开发企业级框架,教授Spring技术核心,企业开发部署环境,规范代码
开发流程及文档——176课时
综合项目实战
飞扬小鸟、飞机大战、俄罗斯方块、T-DMS数据采集项目、T-netctoss项目
、云笔记系统——136小时2W代码量
搭建自己网站
16小时课程实战演练
——企业扶持
学习TDD(2)--实例:ProtoStuffUtil类的测试
>
上篇讲了TDD的步骤和各种好处,俗话说的好,站在岸上是学不会游泳的。所以我们还是要拿个例子出来,实践一下TDD。
因为是**次尝试,我想还是选个简单的例子,之前写的那个PRotoStuffUtil类就很不错。这个类主要负责对象跟byte[]之间的相互转换。可以参考http://blog.csdn.net/mrbcy/article/details/54869113。其实这个类已经写好了,不太符合TDD的规范。但是体验一下还是可以的。
配套的代码已经上传到http://download.csdn.net/detail/mrbcy/9748501
这个类虽然简单但是测试的流程还是很曲折
测试目标
因为这个类是负责对象跟byte[]之间的相互转换,所以我想从两个方面测试它:
**个是能够对复杂的对象进行正确的编码解码
第二个是对复杂对象构成的List、Map进行正确的编码解码
测试代码
来看对象类代码
package tech.mrbcy.mrpc.test.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sun.org.apache.bcel.internal.generic.NEW;
import tech.mrbcy.mrpc.test.enumm.UserType;
public class User {
private int userId;
private String userName;
private boolean lockState;
private UserType userType;
private List<String> addresses = new ArrayList<String>();
private Map<String, String> favoriteMap = new HashMap<String, String>();
// getters and setters
public void addAddress(String address){
addresses.add(address);
}
public void putFavor(String key,String value){
favoriteMap.put(key, value);
}
@Override
public String toString() {
return "User [userId=" userId ", userName=" userName
", lockState=" lockState ", userType=" userType
", addresses=" addresses ", favoriteMap=" favoriteMap
"]";
}
}
看起来对象很复杂了,各种的数据类型和list map也都用上去了。接下来我们编写**个测试。看代码。
@Test
// 对复杂对象进行解码编码
public void testObject(){
User user = new User();
user.setUserId(10086);
user.setUserName("张三");
user.setLockState(true);
user.setUserType(UserType.Vip_USER);
user.addAddress("上海");
user.addAddress("北京");
user.putFavor("tdd", "当当网");
user.putFavor("java","Amazon");
// 保存转换之前的toString结果
String oldString = user.toString();
// 转换
byte[] data = ProtostuffUtil.serializer(user);
User newUser = ProtostuffUtil.deserializer(data, User.class);
// 保存转换之后的toString结果
String newString = newUser.toString();
assertEquals(oldString,newString);
}
执行结果是**。
然后编写第二个测试。
@Test
// 对复杂对象的列表进行编码解码
public void testList(){
List<User> users = new ArrayList<User>();
User user = new User();
user.setUserId(10086);
user.setUserName("张三");
user.setLockState(true);
user.setUserType(UserType.VIP_USER);
user.addAddress("上海");
user.addAddress("北京");
user.putFavor("tdd", "当当网");
user.putFavor("java","Amazon");
users.add(user);
User user2 = new User();
user2.setUserId(10086);
user2.setUserName("张三");
user2.setLockState(true);
user2.setUserType(UserType.VIP_USER);
user2.addAddress("上海");
user2.addAddress("北京");
user2.putFavor("tdd", "当当网");
user2.putFavor("java","Amazon");
users.add(user);
// 保存转换之前的toString结果
String oldString = users.toString();
// 转换
byte[] data = ProtostuffUtil.serializer(users);
List<User> newUsers = ProtostuffUtil.deserializer(data, users.getClass());
// 保存转换之后的toString结果
for(User u : newUsers){
System.out.println(u);
}
String newString = newUsers.toString();
assertEquals(oldString,newString);
}
看到重复代码出现了,暂时不管它,重要的是先让测试**。但是,执行结果是失败。
报出的错误是并发操作List时常出现的错误,就是**外部强行修改了List的内部状态导致的。
我非常的不解,难道对象的List不能和byte[]相互转换?把List包到对象里面试试看。
@Test
// 把List包到对象里进行编码解码
public void testUserPack(){
List<User> users = new ArrayList<User>();
User user = new User();
user.setUserId(10086);
user.setUserName("张三");
user.setLockState(true);
user.setUserType(UserType.VIP_USER);
user.addAddress("上海");
user.addAddress("北京");
user.putFavor("tdd", "当当网");
user.putFavor("java","Amazon");
users.add(user);
User user2 = new User();
user2.setUserId(10086);
user2.setUserName("张三");
user2.setLockState(true);
user2.setUserType(UserType.VIP_USER);
user2.addAddress("上海");
user2.addAddress("北京");
user2.putFavor("tdd", "当当网");
user2.putFavor("java","Amazon");
users.add(user);
UserListPack ulp = new UserListPack();
ulp.setUsers(users);
// 保存转换之前的toString结果
String oldString = ulp.toString();
// 转换
byte[] data = ProtostuffUtil.serializer(ulp);
UserListPack newUlp = ProtostuffUtil.deserializer(data, UserListPack.class);
// 保存转换之后的toString结果
String newString = newUlp.toString();
assertEquals(oldString,newString);
}
UserListPack.java
public class UserListPack {
List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@Override
public String toString() {
return "UserListPack [users=" users "]";
}
}
执行的结果是成功。难道ProtoStuff不能转换List Map这样的数据?于是我又写了一个Map的测试。
@Test
public void testMap(){
Map<Integer, User> uMap = new HashMap<Integer, User>();
User user = new User();
user.setUserId(10086);
user.setUserName("张三");
user.setLockState(true);
user.setUserType(UserType.VIP_USER);
user.addAddress("上海");
user.addAddress("北京");
user.putFavor("tdd", "当当网");
user.putFavor("java","Amazon");
uMap.put(1,user);
User user2 = new User();
user2.setUserId(10086);
user2.setUserName("张三");
user2.setLockState(true);
user2.setUserType(UserType.VIP_USER);
user2.addAddress("上海");
user2.addAddress("北京");
user2.putFavor("tdd", "当当网");
user2.putFavor("java","Amazon");
uMap.put(2,user);
// 保存转换之前的toString结果
String oldString = uMap.toString();
// 转换
byte[] data = ProtostuffUtil.serializer(uMap);
Map<Integer, User> newMap = ProtostuffUtil.deserializer(data, uMap.getClass());
// 保存转换之后的toString结果
String newString = newMap.toString();
assertEquals(oldString,newString);
}
结果失败了。
注意画红框的那里,说明转换出来的Map是空的。看来ProtoStuff真的不能从byte[]转List Map了。
我又去搜了一下Java byte[] to List也没有好的解决办法。
——更新:Google找到了————————–
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
try {
@SuppressWarnings("unchecked")
ArrayList<Object> list = (ArrayList<Object>) ois.readObject();
...
} finally {
ois.close();
}
对应的List to byte[]代码是:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
oos = new ObjectOutputStream(bos);
oos.writeObject(mArrayList);//mArrayList is the array to convert
byte[] buff = bos.toByteArray();
这个代码我还没试。后续看看要不要干脆抛弃ProtoStuff,用上面的方法进行Object和byte[]互转算了。
————————————————-
事到如今我知道ProtoStuffUtil只能转Object,所以只能先修改测试的代码,允许它抛异常,让测试先过掉了。
testMap的**后一句断言修改为assertEquals("{}",newString);
testList的@Test注解修改为@Test(expected = ConcurrentModificationException.class)
这样测试就都**了。
测试重构
这4个测试中的重复代码主要集中在User对象的创建及属性赋值和转换并比较前后字符串这两部分。
创建User的函数,只修改id和userName就足够了。
private User createUser(Integer userId, String userName){
User user = new User();
user.setUserId(userId);
user.setUserName(userName);
user.setLockState(true);
user.setUserType(UserType.VIP_USER);
user.addAddress("上海");
user.addAddress("北京");
user.putFavor("tdd", "当当网");
user.putFavor("java","Amazon");
return user;
}
执行比较的函数
private void doCompare(Object oldObj){
// 保存转换之前的toString结果
String oldString = oldObj.toString();
doCompare(oldObj, oldString);
}
private void doCompare(Object oldObj,String expectStr){
// 转换
byte[] data = ProtostuffUtil.serializer(oldObj);
Object newObj = ProtostuffUtil.deserializer(data, oldObj.getClass());
// 保存转换之后的toString结果
String newString = newObj.toString();
assertEquals(expectStr,newString);
}
重构以后的测试代码变得非常精简。
@Test
// 对复杂对象进行解码编码
public void testObject(){
User user = createUser(10086, "张三");
doCompare(user);
}
重构后4个测试依然是**的。
总结
初步尝试了TDD的流程,虽然没有走的很完整,但是也体验到了单元测试的好处。经过单元测试的类感觉能放心用了。为了避免盲目的信心,以后还要学习测试的相关理论,编写出更合理的测试用例。
下一次要实现某个类的时候再写一次TDD初探,体验完整的流程。
相关推荐:
苏州JAVA培训 苏州JAVA培训班 苏州JAVA培训机构