2008年8月21日星期四

测试脚本

测试脚本

2008年8月6日星期三

Java内部类的分析和整理

package test.jdk;

/**
* 内部类的收集与整理
*
* @author 赵学庆 www.java2000.net
*/
public class InnerTest {
private String instAtt = "实例变量";

private static String staticAtt = "静态变量";

public void test() {
int methodAtt = 1;
final int methodFinalAtt = 2;
// 非静态方法里的内部类
class staticMethodInnerClass {
@Override
public String toString() {
// 非静态方法里无法访问实例的外部变量
System.out.println("非静态方法的内部类可以访问外部类的实例变量:" + instAtt);
System.out.println("非静态方法的内部类可以访问外部类的静态变量:" + staticAtt);
// 非静态方法里无法访问方法的非final的变量
// System.out.println(methodAtt);
System.out.println("非静态方法的内部类可以访问方法的final变量:" + methodFinalAtt);
return "my nickname is white";
}
}
new staticMethodInnerClass().toString();
new Object() {
@Override
public String toString() {
System.out.println("非静态方法的匿名内部类可以访问外部类的实例变量:" + instAtt);
System.out.println("非静态方法的匿名内部类可以访问外部类的静态变量:" + staticAtt);
// 静态方法里匿名内部类无法访问方法的非final的变量
// System.out.println(methodAtt);
System.out.println("非静态方法的匿名内部类可以访问方法的final变量:" + methodFinalAtt);
return "我是匿名内部类";
}
}.toString();
}

public static void main(String blackbat[]) {
int methodAtt = 1;
final int methodFinalAtt = 2;
// 静态方法里的内部类
class staticMethodInnerClass {
@Override
public String toString() {
// 静态方法里无法访问实例的外部变量
// System.out.println(instAtt);
System.out.println("静态方法的内部类可以访问外部类的静态变量:" + staticAtt);
// 静态方法里无法访问方法的非final的变量
// System.out.println(methodAtt);
System.out.println("静态方法的内部类可以访问方法的final变量:" + methodFinalAtt);
return "my nickname is white";
}
}
new staticMethodInnerClass().toString();
new Object() {
@Override
public String toString() {
// 静态方法的匿名内部类不能访问外部类的非静态变量
// System.out.println("非静态方法的匿名内部类可以访问外部类的非静态变量:" + instAtt);
System.out.println("非静态方法的匿名内部类可以访问外部类的静态变量:" + staticAtt);
// 静态方法里匿名内部类无法访问方法的非final的变量
// System.out.println(methodAtt);
System.out.println("非静态方法的匿名内部类可以访问方法的final变量:" + methodFinalAtt);
return "我是匿名内部类";
}
}.toString();
new InnerTest().test();
// 建立静态内部类(static Inner Class)的对象
ImOutClass.StaticInnerClass staticIC = new ImOutClass.StaticInnerClass();
staticIC.access();
/*
* 建立非静态内部类(non-static Inner Class)的对象.
注意这种建立对象的格式 首先创建外部类的对象 然后使用对象.new 来创建。
*/
ImOutClass outC = new ImOutClass();
ImOutClass.InstInnerClass inC = outC.new InstInnerClass();
inC.access();
}
}

class ImOutClass {
private static String staticAtt = " 外部类的类变量 ";

private String instAtt = " 外部类的实例变量 ";

private static String xx = "外部静态变量";

// private String xx = "外部类的实例变量";
// 外部类的非静态方法
public void instanMethod() {
System.out.println(" 和外部类实例方法 ");
}

// 外部类的静态方法
public static void staticMethod() {
System.out.println(" 和外部类静态方法 ");
}

// 静态内部类(static Inner Class)
public static class StaticInnerClass {
public StaticInnerClass() {
System.out.println(" 我是静态内部类 ");
}

public void access() {
System.out.println(" 我可以访问 " + staticAtt);
staticMethod();
System.out.println(" 我可以访问外部的静态变量 " + xx);
// 非静态的方法 instanMethod() 无法从静态的地方使用
// instanMethod();
}
}

// 非静态内部类(non-static Inner Class)
public class InstInnerClass {
public InstInnerClass() {
System.out.println(" 我是成员级内部类,非静态内部类 ");
}

public void access() {
System.out.println(" 我可以访问 " + instAtt);
instanMethod();
staticMethod();
System.out.println(" 我可以访问外部的静态变量 " + xx);
}
}
}

运行结果为

静态方法的内部类可以访问外部类的静态变量:静态变量
静态方法的内部类可以访问方法的final变量:2
非静态方法的匿名内部类可以访问外部类的静态变量:静态变量
非静态方法的匿名内部类可以访问方法的final变量:2
非静态方法的内部类可以访问外部类的实例变量:实例变量
非静态方法的内部类可以访问外部类的静态变量:静态变量
非静态方法的内部类可以访问方法的final变量:2
非静态方法的匿名内部类可以访问外部类的实例变量:实例变量
非静态方法的匿名内部类可以访问外部类的静态变量:静态变量
非静态方法的匿名内部类可以访问方法的final变量:2
我是静态内部类
我可以访问 外部类的类变量
和外部类静态方法
我可以访问外部的静态变量 外部静态变量
我是成员级内部类,非静态内部类
我可以访问 外部类的实例变量
和外部类实例方法
和外部类静态方法
我可以访问外部的静态变量 外部静态变量

关于Hibernate3.2的count返回值的问题

@Override
public int countAllSubject() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
return ((Long) session.createQuery(
"select count(*) from Post where idParent=0").iterate().next())
.intValue();
}

问题关键在那个
(Long)
在我的机器上运行正常,可在一些网友的机器上运行报错
java.lang.ClassCastException: java.lang.Integer

他们修改成(Integer)则运行正常

我的机器上如果改成Integer,则会报错。

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer


经排查,最终确定:

由于我使用的是Hibernate 3.2版本,经确认,这个版本已经把以前返回 Integer的改成了 Long,
因为JPA里面的返回值规定是Long, Hibernate为了兼容这个,所以修改了返回值。

如果你从Hibernate 3.0.x/3.1.x升级到最新的3.2版,一定要注意,3.2版的很多sql函数如count(), sum()的唯一返回值已经从Integer变为Long,如果不升级代码,会得到一个ClassCastException。

这个变化主要是为了兼容JPA,可以在hibernate.org的最新文档中找到说明。

Hibernate Team也提供了一个与原来兼容的解决方案:

Configuration classicCfg = new Configuration();
classicCfg.addSqlFunction( "count", new ClassicCountFunction());
classicCfg.addSqlFunction( "avg", new ClassicAvgFunction());
classicCfg.addSqlFunction( "sum", new ClassicSumFunction());
SessionFactory classicSf = classicCfg.buildSessionFactory();

jsp:include 装载动态页面的问题

提问:
<%
String id="01";//从数据库中获取,非固定值
%>


为什么include中取不到id的值?
如何在根据id的变化,include不同的页面?

解答:
在外面把整个字符串生成了,在放到page里面,不要再page里面再次合成了。

<%
String id = "01";
String pageURL = "hello" + id;
%>


结论:
在许多标签里面,再次嵌套jsp表达式是不行的,不要再里面再次运算了。

JAVA通过Session和Cookie实现网站自动登录的技术

本方案为我这个站点当前使用的,能用,但不保证是最先进的。
原文:http://www.java2000.net/p1010

第一步,登陆的时候一旦选择了[自动登录]的选项,则需要在登陆成功后,附加下面的代码
应为一般网站都提供保存用户名的功能,所以我把这个写到了外面。只有密码是单独处理的。
其中的host就是你的域名
login.jsp
String host = request.getServerName();
Cookie cookie = new Cookie("SESSION_LOGIN_USERNAME", username); // 保存用户名到Cookie
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
if (ParamUtils.getBooleanParameter(request, "savePassword")) {
// 保存密码到Cookie,注意需要加密一下
cookie = new Cookie("SESSION_LOGIN_PASSWORD", MD5.encode(u.getPassword()));
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
}

这样,Cookie就生成了
第二步,在用户访问网站的时候,如果检测到没有登陆,则进行下面的判断。
index.jsp
String usernameCookie = null;
String passwordCookie = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("SESSION_LOGIN_USERNAME".equals(cookie.getName())) {
usernameCookie = cookie.getValue(); // 得到cookie的用户名
}
if ("SESSION_LOGIN_PASSWORD".equals(cookie.getName())) {
passwordCookie = cookie.getValue(); // 得到cookie的密码
}
}
if (usernameCookie != null && passwordCookie != null) { // 如果存在
if(Login.checkLogin(usernameCookie ,passwordCookie)){
// 登陆成功的处理
}else{
// 登陆不成功的处理
}
}
}

一段注册码生成程序,有剪贴板操作

import java.io.*;
import java.text.*;
import java.util.Calendar;
import java.awt.datatransfer.*;

public class T {
private void go() throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("XXXclipse Cracker");
System.out.print("Please Input User ID:");
String userId = br.readLine();
if (userId.length() == 0)
return;
String serialString = getSerial(userId, "200");
System.out.println("Serial Code:" + serialString);
java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new StringSelection(serialString), null);
System.out
.println("Note:The serial code has succefully copied into clipboard!\nPress 'Enter' to exit...");
br.readLine();
}

public static void main(String args[]) throws Exception {
new T().go();
}

public String getSerial(String userId, String licenseNum) {
Calendar cal = Calendar.getInstance();
cal.add(1, 3);
cal.add(6, -1);
NumberFormat nf = new DecimalFormat("000");
licenseNum = nf.format(Integer.valueOf(licenseNum));
String verTime = (new StringBuilder("-")).append(
(new SimpleDateFormat("yyMMdd")).format(cal.getTime())).append("0").toString();
String type = "YE3MP-";
String need = (new StringBuilder(userId.substring(0, 1))).append(type).append("300").append(
licenseNum).append(verTime).toString();
String dx = (new StringBuilder(need))
.append(
"Decompiling this copyrighted software is a violation of both your license agreement and the Digital Millenium Copyright Act of 1998 (http://www.loc.gov/copyright/legislation/dmca.pdf). Under section 1204 of the DMCA, penalties range up to a $500,000 fine or up to five years imprisonment for a first offense. Think about it; pay for a license, avoid prosecution, and feel better about yourself.")
.append(userId).toString();
int suf = decode(dx);
String code = (new StringBuilder(need)).append(String.valueOf(suf)).toString();
return change(code);
}

private int decode(String s) {
int i = 0;
char ac[] = s.toCharArray();
int j = 0;
for (int k = ac.length; j < k; j++)
i = 31 * i + ac[j];
return Math.abs(i);
}

private String change(String s) {
byte abyte0[] = s.getBytes();
char ac[] = new char[s.length()];
int i = 0;
for (int k = abyte0.length; i < k; i++) {
int j = abyte0[i];
if (j >= 48 && j <= 57)
j = ((j - 48) + 5) % 10 + 48;
else if (j >= 65 && j <= 90)
j = ((j - 65) + 13) % 26 + 65;
else if (j >= 97 && j <= 122)
j = ((j - 97) + 13) % 26 + 97;
ac[i] = (char) j;
}
return String.valueOf(ac);
}
}

公交换乘算法(本人并未验证)

/**
* 公交换乘一站的算法思想:
* (注意:车次信息、站点信息、公交信息是等价的都是以HashMap的形式存储信息)
* 1.从数据库中获得所有公交信息存储到ArrayList,每个具体信息的元数据有三个:
* 公交车次、公交站点、该公交站点距离该公交车次的始发站点的站数,具体信息用HashMap保存
* 2.然后把公交信息数据进行结构化,把所有公交站点抽出,再把每一个站点对应的所有车次抽出
* 与其一一对应,单一的车次信息用HashMap存储,站点对应的所有车次信息用ArrayList存储,
* 所有的站点有经过站点的车次信息用HashMap存储
* 3.根据查询要求,分别从结构化以后的公交信息数据中找到,经过出发地的所有车次,经过目的地
* 的所有车次,然后在分别遍历每个车次,筛选出符合要求的中转站点,筛选规则是:每查询出一个
* 站点时,得到该站点距离该站点对应车次的始发站的站数,如果这个站数小于查询站点距离该车次的始
* 发站的站数,那么就符合规则,便把该站点信息保存到符合站点的ArrayList中,反之亦然
* 4.分别得到查询条件中出发地和目的地的中转站点信息(中转站点信息存储在ArrayList中),然
* 后遍历两个中转站点信息的集合,得到最终的具体中转信息(最终中转信息也是用ArrayList存储)
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;

public class T {
private String start = null;// 出发地

private String whither = null;// 目标地

private List schedule = null;// 用于缓存列车时刻表。

private HashMap stationsOfLine = null; // 所有公交线路,每个list存储该线路经过的所有车站。

private HashMap linesOfStation = null;// 所有车站,每个list中存储通过该车站的所有车次。

// private ArrayList startLine = new ArrayList ();//
// 途经出发地的所有车次。
// private ArrayList whitherLine = new ArrayList ();//
// 途经目的地的所有车次。
private ArrayList firLineStaList = new ArrayList();

private ArrayList secLineStaList = new ArrayList();

public T(String start, String whither) {
this.start = start;
this.whither = whither;
try {
this.schedule = this.executeQuery("select busLine,up,stationNo from bus_stations");
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("读取数据库出错");
e.printStackTrace();
}
stationsOfLine = this.getStationsOfLine();
linesOfStation = this.getLinesOfStation();
}

private HashMap getStationsOfLine() {
HashMap map = new HashMap();// 用于 临时存储从schedule中取出的HashMap.
ArrayList line = null;// 每个list存储一个车次的相关车站信息。
String buffer = "a";// 缓存站名。
String temp = null;// 临时存储每次迭代取出的站名,用于与buffer站名比较。
HashMap stationsGroupByLine = new HashMap();// 存储以车次分组後的车站的list
Iterator it = schedule.iterator(); // 迭代器
while (it.hasNext()) {
map = (HashMap) it.next();
temp = (String) map.get("busLine");
if (stationsGroupByLine.containsKey(temp)) {
line = stationsGroupByLine.get(temp);
buffer = (String) ((Map) line.get(0)).get("busLine");
}
if (buffer.equals(temp)) {
line.add(map);// 将同一车次的车站放入一个list中
} else {
if (line != null && !line.isEmpty()) {
stationsGroupByLine.put(buffer, line);// 将由车次分组后的车站构成的list存入一个map
}
line = new ArrayList(); // line重新引用一个新构造的list,以供存储同一车站的车次。
line.add(map);// 将同一车次的车站放入刚刚构造的空list中
}
buffer = temp;// 缓存当前操作的车次。
}
return stationsGroupByLine;
}

private HashMap getLinesOfStation() {
HashMap map = new HashMap();// 用于 临时存储从schedule中取出的HashMap.
ArrayList station = null;// 每个list存储一个经过该车站的相关车次信息。
String buffer = "a";// 缓存车次。
String temp = null;// 临时存储每次迭代取出的车次,用于与buffer车次比较。
HashMap linesGroupBystation = new HashMap();// 存储以车站分组後的车次的list
Iterator it = schedule.iterator(); // 迭代器
while (it.hasNext()) {
map = (HashMap) it.next();
temp = (String) map.get("up");
if (linesGroupBystation.containsKey(temp)) {
// station存储temp车次对应的站点信息
station = linesGroupBystation.get(temp);
// 从station中取出已经放入linesGroupBystation车站信息,缓存改车站的名字
// 与刚取出的Map中存储到车站信息进行比较
buffer = (String) ((Map) station.get(0)).get("up");
}
if (buffer.equals(temp)) {
// 如果station中几经存在该站点信息,那么,本站和station中存储到是同一站,所以
// 将同一车次的车站放入一个list中
station.add(map);
} else {
if (station != null && !station.isEmpty()) {
// 将由车次分组后的车站构成的list存入一个map
linesGroupBystation.put(buffer, station);
}
// line重新引用一个新构造的list,以供存储经过另一车站的所有车次
station = new ArrayList();
station.add(map);// 将同一车次的车站放入刚刚构造的空list中
}
buffer = temp;// 缓存当前操作的车次。
}
return linesGroupBystation;
}

/**
* 站点筛选规则:把符合规则的站点添分别放入
*
* @param startSta
* @param whitherSta
*/
private void getStationsInLine(String startSta, String whitherSta) {
// 获得经过初始站点的所有公交车次
ArrayList firTrainLine = linesOfStation.get(startSta);
// 获得经过所有目的站点的公交车次
ArrayList secTrainLine = linesOfStation.get(whitherSta);
ArrayList station;
HashMap line = null;
int transferStaNo = 0;
// String stationName = null;
String trainNo = "";
if (firTrainLine != null) {
Iterator firIt = firTrainLine.iterator();
while (firIt.hasNext()) {
// 取出一个存储车站信息HashMap
line = (HashMap) firIt.next();
// 取出车次信息
trainNo = (String) line.get("busLine");
transferStaNo = (Integer) line.get("stationNo");
// 取出车次trainNo经过的所有站点信息
station = stationsOfLine.get(trainNo);
Iterator it = station.iterator();
while (it.hasNext()) {
Map map = (Map) it.next();// trainNo's map.
int i = (Integer) map.get("stationNo");
// 筛选站点规则:如果该站点距离初始站点距离比出发站点的距离初始站点的距离大,那么就把该站点存储到
// firLineStaList,反之就做反车了,所以那些站点不必加入firLineStaList中
if (i > transferStaNo) {
//
firLineStaList.add(map);
}
}
}
}
if (secTrainLine != null) {
Iterator secIt = secTrainLine.iterator();
while (secIt.hasNext()) {
line = (HashMap) secIt.next();
trainNo = (String) line.get("busLine");
transferStaNo = (Integer) line.get("stationNo");
station = stationsOfLine.get(trainNo);
Iterator it = station.iterator();
while (it.hasNext()) {
Map map = (Map) it.next();
int i = (Integer) map.get("stationNo");
if (i < transferStaNo) {
secLineStaList.add(map);
}
}
}
}
}

/**
* create date:2008-5-19 author:Administrator
*
* @return
*/
private ArrayList checkCrossLine() {
ArrayList crossLineList = new ArrayList();// 相交线路的集合,即是所有的换乘方法的集合
ArrayList lsStart = firLineStaList;// 经过起点站的所有车次的经停站站信息。
ArrayList lsEnd = secLineStaList;// 经过目的站的所有车次的经停站站信息。
if (lsStart != null && !lsStart.isEmpty() && lsEnd != null && !lsEnd.isEmpty()) {
for (Map mapStart : lsStart) {
for (Map mapEnd : lsEnd) {
if (IsInTheSameCity(mapStart.get("up"), mapEnd.get("up"))) {
// 将相交线路信息存入crossLine,存储某一个具体的换乘方法
Map crossLine = new HashMap(4, 0.8f);
// 把第一次要做到车次放如crossLine
crossLine.put("firstLine", mapStart.get("busLine"));
// 把要换乘的车次放入到crossLine
crossLine.put("secondLine", mapEnd.get("busLine"));
// 把中转站点放入到crossLine
crossLine.put("transferSta", mapEnd.get("up"));
// crossLine.put("transferSta",(String)startInf.get("up"));
// 将包含相交线路信息的HashMap存入List
// 也即是把具体某个换乘方法放入crossLineList
crossLineList.add(crossLine);
} else {
continue;
}
}
}
} else {
crossLineList = null;
}
return crossLineList;
}

private boolean IsInTheSameCity(String station1, String station2) {
if (station1.contains(station2) || station2.contains(station1)) {
// System.out.println(station1+"#########"+station2);
return true;
} else {
return false;
}
}

public ArrayList getSchemaOfTransfer() {
this.getStationsInLine(this.start, this.whither);
return this.checkCrossLine();
}

public static void main(String[] args) {
T tb = new T("前门", "天安门西");
// tb.getSchemaOfTransfer();
for (Map map : tb.getSchemaOfTransfer()) {
System.out.println(map);
System.out.println("您好,您可以先乘坐 " + map.get("firstLine") + " 到 " + map.get("transferSta")
+ " 然后换乘 " + map.get("secondLine") + " 便可到达,不要错过站吆 !");
}
// System.out.println(tb.secLineStaList.size());
}

private Connection getConnection() {
Connection con = null;
String url = "jdbc:mysql://127.0.0.1:3306/souwhat?autoReconnect=true&useUnicode=true&characterEncoding=GBK&mysqlEncoding=GBK";
String user = "root";
String psWord = "";
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("The Exception at load the Driver");
}
try {
con = DriverManager.getConnection(url, user, psWord);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("The Exception at creat the connection");
}
return con;
}

private void closeConnection(Connection conn) throws Exception {
if (conn != null) {
conn.close();
}
}

private List executeQuery(String sql) throws Exception {
// System.out.println("executeQuery(sql): " + sql);
List list = new ArrayList();
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = getConnection();
stmt = conn.createStatement();
System.out.println(sql);
rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
while (rs.next()) {
Map map = new HashMap();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
// 每一行所有列存入HashMap中
map.put(rsmd.getColumnName(i), rs.getObject(i));
}
// 所有行存入List中
list.add(map);
}
} catch (Exception e) {
System.out.println("数据库查询出错!");
e.printStackTrace();
} finally {
if (rs != null)
rs.close();
closeConnection(conn);
}
return list;
}
}

文件压缩和解压缩的辅助类

import java.io.*;
import java.util.*;
import java.util.zip.*;

public class T {
public static int bufsize = 8192;

private String zipBase;

private int maxFileNameLength;

private long totalLength;

private long bytesHandled;

private String getSpace(int num) {
String space = "";
for (int i = 0; i < num; i++) {
space += " ";
}
return space;
}

private void getLength(File path) {
if (path.isFile()) {
totalLength += path.length();
if (path.getPath().length() > maxFileNameLength) {
maxFileNameLength = path.getPath().length();
}
} else {
File[] fs = path.listFiles();
for (int i = 0; i < fs.length; i++) {
getLength(fs[i]);
}
}
}

private String lengthString(long fileLength) {
long newValue = 0;
String size = null;
if (fileLength < 1024) {
size = fileLength + " B";
} else if (fileLength < (1024 * 1024)) {
newValue = fileLength / 1024;
size = newValue + " KB";
} else if (fileLength < (1024 * 1024 * 1024)) {
newValue = fileLength / (1024 * 1024);
size = newValue + " MB";
} else {
newValue = fileLength / (1024 * 1024 * 1024);
size = newValue + " GB";
}
return size;
}

public void zip(String path) throws Exception {
zip(path, null);
}

public void zip(String path, String dest) throws Exception {
File f = new File(path);
if (!f.exists()) {
System.out.println("File : " + path + " Not Exists!");
return;
}
getLength(f);
System.out.println("total " + lengthString(totalLength) + " to zip");
String path2 = "";
for (int i = 0; i < path.length(); i++) {
char c = path.charAt(i);
if (c == '\\') {
c = '/';
}
path2 += c;
}
path = path2;
zipBase = path.substring(path.lastIndexOf("/") == -1 ? 0 : path.lastIndexOf("/") + 1);
if (dest == null) {
if (f.isFile()) {
if (dest == null) {
zipBase = "./";
dest = path.substring(0, (path.lastIndexOf(".") == -1 ? path.length() : path
.lastIndexOf(".")))
+ ".zip";
}
} else {
path2 = path.substring(0, path.lastIndexOf("/") == -1 ? path.length() : path
.lastIndexOf("/"));
if (path.equals(path2)) {
dest = ".";
}
dest = path2
+ "/"
+ zipBase.substring(0, (zipBase.lastIndexOf(".") == -1 ? zipBase.length() : zipBase
.lastIndexOf("."))) + ".zip";
}
}
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(dest));
zipFile(f, zipOut);
zipOut.close();
System.out.print("\r100%\t");
System.out.println(path + " has been compressed to zip file : " + dest + getSpace(40));
}

public void zipFile(File f, ZipOutputStream zipOut) throws Exception {
if (f.isDirectory()) {
File[] fs = f.listFiles();
for (int i = 0; i < fs.length; i++) {
zipFile(fs[i], zipOut);
}
} else {
String path = f.getPath();
FileInputStream fileIn = new FileInputStream(path);
String entryName = path;
int basePos = path.indexOf(zipBase);
if (basePos > 0) {
entryName = path.substring(basePos);
}
ZipEntry theEntry = new ZipEntry(entryName);
theEntry.setSize(f.length());
zipOut.putNextEntry(theEntry);
byte[] buffer = new byte[bufsize];
int bytesRead = fileIn.read(buffer, 0, bufsize);
bytesHandled += bytesRead;
while (bytesRead > 0) {
zipOut.write(buffer, 0, bytesRead);
bytesRead = fileIn.read(buffer, 0, bufsize);
bytesHandled += bytesRead;
int percent = (int) (((double) bytesHandled / totalLength) * 100);
System.out.print("\r" + percent + "% ");
if (totalLength > 1024 * 1024 * 80) {
int j;
for (j = 0; j < percent % 4 + 1; j++) {
System.out.print(">");
}
for (int x = 0; x < 4 - j; x++) {
System.out.print(" ");
}
}
System.out.print(" Compress File " + path + getSpace(maxFileNameLength - path.length()));
}
fileIn.close();
zipOut.closeEntry();
}
}

public void unzip(String zipFileName) throws Exception {
unzip(zipFileName, null);
}

public void unzip(String zipFileName, String dest) throws Exception {
File f = new File(zipFileName);
if (!f.exists()) {
System.out.println("Zip File : " + zipFileName + " Not Exists!");
return;
}
byte[] buffer = new byte[bufsize];
ZipFile zf = new ZipFile(zipFileName);
ZipEntry theEntry = null;
Enumeration enumer = zf.entries();
while (enumer.hasMoreElements()) {
theEntry = (ZipEntry) enumer.nextElement();
totalLength += theEntry.getSize();
if (theEntry.getName().length() > maxFileNameLength) {
maxFileNameLength = theEntry.getName().length();
}
}
System.out.println("Zip File " + lengthString(f.length()) + " and Total "
+ lengthString(totalLength) + " Data to unzip");
enumer = zf.entries();
while (enumer.hasMoreElements()) {
theEntry = (ZipEntry) enumer.nextElement();
String entryName = theEntry.getName();
String entryName2 = "";
for (int i = 0; i < entryName.length(); i++) {
char c = entryName.charAt(i);
if (c == '\\') {
c = '/';
}
entryName2 += c;
}
entryName = entryName2;
zipBase = ".";
if (dest != null) {
if (dest.endsWith("/")) {
dest = dest.substring(0, dest.length() - 1);
}
zipBase = dest;
}
String tmpFolder = zipBase;
int begin = 0;
int end = 0;
while (true) {
end = entryName.indexOf("/", begin);
if (end == -1) {
break;
}
tmpFolder += "/" + entryName.substring(begin, end);
begin = end + 1;
f = new File(tmpFolder);
if (!f.exists()) {
f.mkdir();
}
}
OutputStream os = new FileOutputStream(zipBase + "/" + entryName);
InputStream is = zf.getInputStream(theEntry);
int bytesRead = is.read(buffer, 0, bufsize);
bytesHandled += bytesRead;
while (bytesRead > 0) {
os.write(buffer, 0, bytesRead);
bytesRead = is.read(buffer, 0, bufsize);
bytesHandled += bytesRead;
System.out.print("\r");
int percent = (int) (((double) bytesHandled / totalLength) * 100);
System.out.print("\r" + percent + "% ");
if (totalLength > 1024 * 1024 * 80) {
int j;
for (j = 0; j < percent % 4 + 1; j++) {
System.out.print(">");
}
for (int x = 0; x < 4 - j; x++) {
System.out.print(" ");
}
}
System.out.print(" Unzip File " + entryName
+ getSpace(maxFileNameLength - entryName.length()));
}
is.close();
os.close();
}
System.out.println("\r100% Zip File : " + zipFileName + " has been unCompressed to " + dest
+ "/ !" + getSpace(40));
}

public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.out.println("usage : java T -zip[-unzip] filename");
return;
}
T zip = new T();
String dest = null;
if (args[0].equals("-zip")) {
if (args.length > 2) {
dest = args[2];
}
zip.zip(args[1], dest);
}
if (args[0].equals("-unzip")) {
if (args.length > 2) {
dest = args[2];
}
zip.unzip(args[1], dest);
}
}
}

属性文件操作辅助类,采用Properties和ResourceBundle两种方式

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Properties;
import java.util.ResourceBundle;

/**
* 操作属性文件.

* 可以为我们的程序带来更方便的移植性,下面是一个示例,可以读、写、更改属性

* 读采用了两种方式,一种是采用Properties类

* 另外一种是采用资源绑定类ResourceBundle类

* 下面是源程序,里面有详细的注释:
*
* @author 赵学庆 www.java2000.net
*/
public class OperatePropertiesFile {
public OperatePropertiesFile () {
}

/**
* 采用Properties类取得属性文件对应值
*
* @parampropertiesFileNameproperties文件名,如a.properties
* @parampropertyName属性名
* @return根据属性名得到的属性值,如没有返回""
*/
public static String getValueByPropertyName(String propertiesFileName, String propertyName) {
String s = "";
Properties p = new Properties();// 加载属性文件读取类
FileInputStream in;
try {
// propertiesFileName如test.properties
in = new FileInputStream(propertiesFileName);// 以流的形式读入属性文件
p.load(in);// 属性文件将该流加入的可被读取的属性中
in.close();// 读完了关闭
s = p.getProperty(propertyName);// 取得对应的属性值
} catch (Exception e) {
e.printStackTrace();
}
return s;
}

/**
* 采用ResourceBundel类取得属性文件对应值,这个只能够读取,不可以更改及写新的属性
*
* @parampropertiesFileNameWithoutPostfixproperties文件名,不带后缀
* @parampropertyName属性名
* @return根据属性名得到的属性值,如没有返回""
*/
public static String getValueByPropertyName_(String propertiesFileNameWithoutPostfix,
String propertyName) {
String s = "";
// 如属性文件是test.properties,那此时propertiesFileNameWithoutPostfix的值就是test
ResourceBundle bundel = ResourceBundle.getBundle(propertiesFileNameWithoutPostfix);
s = bundel.getString(propertyName);
return s;
}

/**
* 更改属性文件的值,如果对应的属性不存在,则自动增加该属性
*
* @parampropertiesFileNameproperties文件名,如a.properties
* @parampropertyName属性名
* @parampropertyValue将属性名更改成该属性值
* @return是否操作成功
*/
public static boolean changeValueByPropertyName(String propertiesFileName, String propertyName,
String propertyValue) {
boolean writeOK = true;
Properties p = new Properties();
InputStream in;
try {
in = new FileInputStream(propertiesFileName);
p.load(in);//
in.close();
p.setProperty(propertyName, propertyValue);// 设置属性值,如不属性不存在新建
// p.setProperty("testProperty","testPropertyValue");
FileOutputStream out = new FileOutputStream(propertiesFileName);// 输出流
p.store(out, "");// 设置属性头,如不想设置,请把后面一个用""替换掉
out.flush();// 清空缓存,写入磁盘
out.close();// 关闭输出流
} catch (Exception e) {
e.printStackTrace();
}
return writeOK;
}
}

JSON辅助类,可以把一些对象和集合转化为标准的JSON格式

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* 序列化对象为JSON格式 遵循JSON组织公布标准
*
* @date 2008/05/07
* @version 1.0.0
*/
public class JsonUtil {
/** Commons Logging instance. */
private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
.getLog(JsonUtil.class);

/**
* @param obj 任意对象
* @return String
*/
public static String object2json(Object obj) {
StringBuilder json = new StringBuilder();
if (obj == null) {
json.append("\"\"");
} else if (obj instanceof String || obj instanceof Integer || obj instanceof Float
|| obj instanceof Boolean || obj instanceof Short || obj instanceof Double
|| obj instanceof Long || obj instanceof BigDecimal || obj instanceof BigInteger
|| obj instanceof Byte) {
json.append("\"").append(string2json(obj.toString())).append("\"");
} else if (obj instanceof Object[]) {
json.append(array2json((Object[]) obj));
} else if (obj instanceof List) {
json.append(list2json((List) obj));
} else if (obj instanceof Map) {
json.append(map2json((Map) obj));
} else if (obj instanceof Set) {
json.append(set2json((Set) obj));
} else {
json.append(bean2json(obj));
}
return json.toString();
}

/**
* @param bean bean对象
* @return String
*/
public static String bean2json(Object bean) {
StringBuilder json = new StringBuilder();
json.append("{");
PropertyDescriptor[] props = null;
try {
props = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
} catch (IntrospectionException e) {}
if (props != null) {
for (int i = 0; i < props.length; i++) {
try {
String name = object2json(props[i].getName());
String value = object2json(props[i].getReadMethod().invoke(bean));
json.append(name);
json.append(":");
json.append(value);
json.append(",");
} catch (Exception e) {}
}
json.setCharAt(json.length() - 1, '}');
} else {
json.append("}");
}
return json.toString();
}

/**
* @param list list对象
* @return String
*/
public static String list2json(List list) {
StringBuilder json = new StringBuilder();
json.append("[");
if (list != null && list.size() > 0) {
for (Object obj : list) {
json.append(object2json(obj));
json.append(",");
}
json.setCharAt(json.length() - 1, ']');
} else {
json.append("]");
}
return json.toString();
}

/**
* @param array 对象数组
* @return String
*/
public static String array2json(Object[] array) {
StringBuilder json = new StringBuilder();
json.append("[");
if (array != null && array.length > 0) {
for (Object obj : array) {
json.append(object2json(obj));
json.append(",");
}
json.setCharAt(json.length() - 1, ']');
} else {
json.append("]");
}
return json.toString();
}

/**
* @param map map对象
* @return String
*/
public static String map2json(Map map) {
StringBuilder json = new StringBuilder();
json.append("{");
if (map != null && map.size() > 0) {
for (Object key : map.keySet()) {
json.append(object2json(key));
json.append(":");
json.append(object2json(map.get(key)));
json.append(",");
}
json.setCharAt(json.length() - 1, '}');
} else {
json.append("}");
}
return json.toString();
}

/**
* @param set 集合对象
* @return String
*/
public static String set2json(Set set) {
StringBuilder json = new StringBuilder();
json.append("[");
if (set != null && set.size() > 0) {
for (Object obj : set) {
json.append(object2json(obj));
json.append(",");
}
json.setCharAt(json.length() - 1, ']');
} else {
json.append("]");
}
return json.toString();
}

/**
* @param s 参数
* @return String
*/
public static String string2json(String s) {
if (s == null)
return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
switch (ch) {
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
if (ch >= '\u0000' && ch <= '\u001F') {
String ss = Integer.toHexString(ch);
sb.append("\\u");
for (int k = 0; k < 4 - ss.length(); k++) {
sb.append('0');
}
sb.append(ss.toUpperCase());
} else {
sb.append(ch);
}
}
}
return sb.toString();
}
}

Java中的鼠标和键盘事件

Java中的鼠标和键盘事件
1、使用MouseListener借口处理鼠标事件
鼠标事件有5种:按下鼠标键,释放鼠标键,点击鼠标键,鼠标进入和鼠标退出
鼠标事件类型是MouseEvent,主要方法有:
getX(),getY() 获取鼠标位置
getModifiers() 获取鼠标左键或者右键
getClickCount() 获取鼠标被点击的次数
getSource() 获取鼠标发生的事件源
事件源获得监视器的方法是addMouseListener(),移去监视器的方法是removeMouseListener()
处理事件源发生的时间的事件的接口是MouseListener 接口中有如下的方法
mousePressed(MouseEvent) 负责处理鼠标按下事件
mouseReleased(MouseEvent) 负责处理鼠标释放事件
mouseEntered(MouseEvent) 负责处理鼠标进入容器事件
mouseExited(MouseEvent) 负责处理鼠标离开事件
mouseClicked(MouseEvent) 负责处理点击事件
2、使用MouseMotionListener接口处理鼠标事件
事件源发生的鼠标事件有2种:拖动鼠标和鼠标移动
鼠标事件的类型是MouseEvent
事件源获得监视器的方法是addMouseMotionListener()
处理事件源发生的事件的接口是MouseMotionListener 接口中有如下的方法
mouseDragged() 负责处理鼠标拖动事件
mouseMoved() 负责处理鼠标移动事件
3、控制鼠标的指针形状
setCursor(Cursor.getPreddfinedCursor(Cursor.鼠标形状定义)) 鼠标形状定义见(书 P 210)
4、键盘事件
键盘事件源使用addKeyListener 方法获得监视器
键盘事件的接口是KeyListener 接口中有3个方法
public void keyPressed(KeyEvent e) 按下键盘按键
public void keyReleased(KeyEvent e) 释放键盘按键
public void keyTypde(KeyEvent e) 按下又释放键盘按键

ISBN(国际标准书号)的校验

public class T {
public static void main(String[] args) {
System.out.println("9787302155638 " + ISBN.checkISBN("9787302155638"));
System.out.println("7564105607 " + ISBN.checkISBN("7564105607"));
System.out.println("730213880X " + ISBN.checkISBN("730213880X"));
System.out.println("7302138800 " + ISBN.checkISBN("7302138800"));
System.out.println("9790000000000 " + ISBN.checkISBN("9790000000000"));
try {
System.out.println(ISBN.checkISBN("9770000000000"));
} catch (Exception e) {
System.out.println("9770000000000 " + e.getMessage());
}
try {
System.out.println(ISBN.checkISBN("123456545"));
} catch (Exception e) {
System.out.println("123456545 " + e.getMessage());
}
}
}

final class ISBN {
/**
* 根据输入的ISBN号,检验ISBN的有效性。

* 依据 GB/T 5795-2006 和 ISO 2108:2005 ISBN

* 10位标准和13位标准实现(13位标准自2007年1月1日开始实行,在此之前采用10位标准)。
*
* @param String isbn:需要进行校验的ISBN字符串
* @return true:所输入的ISBN校验正确;
false:所输入的ISBN校验错误
*/
public static boolean checkISBN(String isbn) {
int count = 0;
int checkBitInt = 0;
// 将ISBN数据全取大写字母
// isbn = isbn.toUpperCase();
char[] cs = isbn.toCharArray();
switch (isbn.length()) {
case 10:
// ****************************************************************
// 当ISBN为10位时,进行的校验,用于2007年1月1日前的出版物
// 数据格式:从左至右前9位为ISBN数据,第10位为校验位
// 校验方法:
// (1) 从左至右将前9位数据从10开始至2进行编号,作为位权
// (2) 将9位数据与各位位权进行加权,并求其9位和(称为加权和,记作M)
// (3) 第10位校验位计算方法,校验位为C:
// M + C ≡ 0 (mod 11)
// C为10时,记作“X”
// ****************************************************************
// 取出前9位数字进行加权和计算
for (int i = 0; i < 9; i++) {
// 若前9位数据中有非数字字符,则抛出异常
if (cs[i] < '0' || cs[i] > '9') {
throw new ISBNFormatException("ISBN " + isbn + " 第 " + (i + 1) + " 位中出现非法字符 " + cs[i]);
}
int c = cs[i] - '0';
// 求加权和
count += c * (10 - i);
}
// 取出校验位数据0~9和X符合校验字符要求
if (cs[9] >= '0' && cs[9] <= '9') {
checkBitInt = cs[9] - '0';
} else if (cs[9] == 'X' || cs[9] == 'x') {
// 校验位中的“X”表示数据“10”
checkBitInt = 10;
} else {
// 非0~9或X时抛出异常
throw new ISBNFormatException("ISBN " + isbn + " 第 10 位中出现非法字符 " + cs[9]);
}
// 进行校验
if ((count + checkBitInt) % 11 == 0) {
return true; // 校验成功
} else {
return false; // 校验失败
}
case 13:
// ****************************************************************
// 当ISBN为13位时,进行的校验,用于2007年1月1日后的出版物
// 数据格式:从左至右前12位为ISBN数据,第13位为校验位
// 校验方法:
// (1) 从左至右将前12位数的取其奇位数和和偶位数和
// (2) 将偶位数和乘3,并其与奇位数和的和,得加权和
// (3) 第13位校验位计算方法,校验位为C:
// M + C ≡ 0 (mod 10)
// ****************************************************************
// ISBN为13位数据时,前3位目前只能是“978”(已实行)或“979”(暂未实行)
if (!isbn.startsWith("978") && !isbn.startsWith("979")) {
throw new ISBNFormatException("ISBN-13 格式不符合标准");
}
// 取出前12位数字进行加权和计算
int countEven = 0;
int countOdd = 0;
for (int i = 0; i < 12; i++) {
int c = cs[i] - '0';
// 若前12位数据中有非数字字符,则抛出异常
if (c <> 9) {
throw new ISBNFormatException("ISBN " + isbn + " 第 " + (i + 1) + " 位中出现非法字符 " + cs[i]);
}
// 分别计算奇位数和偶位数的和
if ((i & 0x1) == 0) {
countOdd += c;
} else {
countEven += c;
}
}
// 求加权和
count = countOdd + (countEven * 3);
// 取出校验位数据
if (cs[12] < '0' || cs[12] > '9') {
// 校验位为非0~9字符时,抛出异常
throw new ISBNFormatException("ISBN " + isbn + " 第 13 位中出现非法字符 " + cs[12]);
}
checkBitInt = cs[12] - '0';
// 进行校验
if ((count + checkBitInt) % 10 == 0) {
return true; // 校验成功
} else {
return false; // 校验失败
}
default:
// ISBN为非10位或13位时抛出异常
throw new ISBNFormatException("ISBN 格式不符合标准");
}
}
}

class ISBNFormatException extends RuntimeException {
private static final long serialVersionUID = 1L;

public ISBNFormatException() {
super("ISBN Error ...");
}

public ISBNFormatException(String arg0) {
super(arg0);
}
}

将字符串按照单词完全反转-大公司面试题

问题来源于论坛的一个题目,不过这个问题可能会有好多人面试时被问到,所以整理出来。
原文地址:http://topic.csdn.net/u/20080711/14/00183de8-5fdf-4fac-a39c-c4dc343b0de5.html


将字符串 String oldstr="I am a programmer"完全反转为"programmer a am I",
最好不用函数,自己写,当然也可以用
这样的 题目很多人写不出,真是汗啊!我是用链表实现的,但是比较繁琐,算是过关了,今天特来寻求最好的解决方案

我给出的代码

public static void reverse() {
String s = "i am a programmer "; // 几个空格的数量分别为1,2,3,4个
String[] eg = s.split(" ", -1);
String result = "";
for (int i = eg.length - 1; i > 0; i--) {
result += eg[i] + " ";
}
result += eg[0]; // 这里要注意第一个字符的前面是不能增加空格的。否则就多了一个空格
System.out.println(result);
}

原理很简单,用空格分隔,但一定要指定第二个参数为-1,否则如果在字符串的末尾出现了空格,则会引起数据丢失。
运行结果
programmer a am i

塞翁失马又得马,福祸循环,人生如此相似

这几天在论坛被人骂,有人支持,也有许多朋友报不平。我想这到没什么,我又不是为了他们而活着。不过倒让我仔细想了想这么多年的人生经历。撰写此文,希望能对大家平衡心态有所帮助。

以前有一句谚语,“塞翁失马,焉知非福;塞翁得马,焉知非祸”。匆匆走过了36年,经常不经意间印证了它。

从小在农村,上中学时有机会从农村的小初中,转到北京燕郊的重点中学。当时出奇的不想去,结果留在了本乡的中学。也认识了我的2个终身的朋友。可以肝胆相照的朋友。

初中成绩很好,被许多老师看好,自己也是有点得意。一次数学考试,第一道题是1- -1 = ? 也就是一减去负一等于几,全校6个班,300多人,只有我一个人答错了。

中考不理想,虽然也到了重点中学的线,但在班上排名24号。我有点泄气,学习也就不是很上心。此时接触到了计算机。那是1988年,学校只有 AppleII增强型,和10几台Com35 机器。反正怎么学都赶不上他们,就迷上了这个,还有围棋。 大家白天偷者去机房,晚自习就偷着下围棋,杀得昏天黑地。也认识了几个喜爱下棋的老师,还参加了县里的比赛,几百人吧,成绩不错,进入了前十名。 计算机竞赛也拿了二等奖,一等奖是我哥们,他后来去了国防科技大学。高考,成绩再次不理想,比预想的分数少了至少30分。将就的考入了天津大学化学系。

都是精英啊,全班25人,我基本在中等偏下,唯一的一次努力,进入了第8名,然后就再也不学习了。唯一可以欣慰的就是所有科目最少的61分,没有补 考。四级也是凭着高中的底子,70多分拿下。也造成了我到如今口语不行,只能阅读的后果。周围的伙伴都是买了好多的书,还有磁带,打着手电筒学习,我则呼 呼睡大觉。我的业务时间基本做2件事,第一去和计算机系的上机房,学汇编和Turbo C,Pascal, 还有就是打游戏,三国志II,三国I,大富翁II。大学的计算机比赛只参加了一次,还算不错,三等奖,因为自己马虎把一道最简单的题目给看错了,最后的几 个难题到是解答的还可以。后来听说所有参加决赛的人中,只有我一个算错了。和初中的经历出奇的相似。

毕业了,去了化工厂,每月600元工资。由于性格内向,又没有社会关系,一干就是5年。从22岁到27岁,人生最宝贵的5年就这样度过了。头一年, 在下面体验生活,什么脏累的活都干过。由于工作态度和能力还可以,赶上原来的副主任升到了副厂长,我就当上了车间技术副主任的职务。车间生产一台能比一日 按好,日子应该好过了吧,结果97年,污染搬迁,车间被人兼并了。工厂被搬迁到一个很远的地方,要做30分钟的班车。 新工厂是人家建的,车间领导也是人家说了算。干了1年,没兴趣了,因为自己熟悉工控系统,所以调到了仪表组,享受主任的待遇。

1999年,有了第一个小屋,装上了ISDN。我开始上网,做网页,学些html,学习perl,那时候有支持cgi的免费空间的. 那时候资料非常少,我的小网站也有了一点眉目。上网4个月,电信来收电话费,2700多元,我都傻了。我们夫妻2个每个月所有的收入加在一起才1500 元。一查原因,被告知我的ISDN开启了2B,每次连接都按照一次通话收取费用。我晕。。。(好像那时候还不流行这个晕)。

2000年结婚,出去找了一个网站的工作,我的筹码就是我的网站。我那时对页面已经算比较熟悉了,虽然很难看。干了10多天,没法做了,就去了另一 个公司,这次面试是非常成功的。我对技术的理解直接被对方负责人看中,我成功的加盟了。终于拿到了每月2000元的工资了。哇,好多啊!比以前多2倍哦。 我拥有了第一个顶级域名,php2000,在2003年被我放弃了。使用的技术是php,而没有选择asp. 因为当时asp很火,但会的人太多了,我想我还是看看别的吧。那时也申请了我的第一个QQ号,一直用到现在。我在公司是很受重视的,另外几个人很快就只能 给我搭下手了。我再次感到了希望。

三个月后,公司被人骗了300万现金,倒闭了。我们又得再次寻找出路了。哭啊.... 正发愁着,一个人来到了公司,他和我们的领导熟悉,来挑人。原因是他们的最大领导发现了一个网站,把它找去说,看这个网站多好。 他说,我认识做网站的这个人,于是他就来到了这里。我们到了开发区面试。我留下了,但面试我的不是应该面试我的总工,而是一个常务副总,这也让我以后遇到 了一些麻烦。工资涨到了2500,是拿到手了的,税前我想应该有2800吧。

在新公司努力着,和一个同样技术牛人关系很好,他现在就职于中石化,他领着我进入了Java。和一个校友关系很好,他负责硬件,服务器和网络,我的网站就放在他那里,呵呵。

2001年,公司重组,部门经理调任另一个事业部做负责人,我被选中做了部门经理,原因是我的年纪比较大(呵呵),能压得住阵脚,人缘也不错,技术 也好。我的工资到了3500。再次感到了希望。虽然我没有赶上互联网泡沫,但我对自己的日子过得还算顺心。至少存折里开始有钱了。

2002年天津党代会,人大政协会议使用了我们开发的签到和会务服务系统,我由于参与了开发,配合我的牛人师傅,对系统的了解,以及在特殊异常情况下的良好心态,坐镇系统指挥中心。这一次让总工对我的评价猛增,他不再挤兑我了。前途一片光明啊。大家的心气都很高。

2003年,公司不知道出了什么问题,大领导被解职了,公司也转型到了硬件,以系统集成为主,软件不自己开发,而是委托别人。我们组被划分到了系统集成事业部,事业到了低谷,拿70%的工资,人员开始有离开,我也考虑离开了。

经朋友介绍到了一个制药企业,总裁助理直接面试的。公司很大,产品很好,可是竟然没有软件基础,只有几个人勉强维护者2个ERP。我的电脑也是一周 后才到,配置很一般。期间没事干,就安装了一个Linux 下面的Oracle. 由于我以前的php2000网站是linux+php+mysql的,所以linux不陌生。还好,虽然遇到了n多的问题,不过最后还是装上 了,Oracle 9i。当初学习J2EE的东西也发挥了作用,公司领导决定走Java路线。并决定购买Weblogic 和 Oracle。我正好大显身手。

非典了,还好没收到影响。闷在屋子里鼓捣东西,由于工作表现好,2个月后提前转正,并被任命为软件组的负责人。有10几条枪,干着公司的小项目,维 护者几个大系统,进行一些二次开发等,忙得不一乐乎。 随着几个软件投入实际的使用,解决了实际的业务问题,软件组的地位也逐步的提高了。前途再次一片光明。

2005年,我由于工作表现好,申请升级到中层副部长级,论资格,论贡献都没问题,在各个部门的人缘也很好,特别是一些部门的基层负责人。因为我经 常帮他们解决问题,他们在人力资源审查时都替我说好话。今天想起来还是很感动。你帮助别人,你总会遇到需要他们帮你的时候,当然,他们是自愿的。审查完 毕,报总裁审批,基本就没问题了。 天有不测风云,当初找我进公司的总裁助理此时离职了。我的审批竟然被驳回了。我后来内部了解了一下,成也萧何,败也萧何,当初总裁助理进入公司时,没有和 人力资源部长搞好关系,而人力部长以前是公司营销的一把手,创业时累坏了身体,才转到二线的。他们之间早就有矛盾,我被株连了。路就这样断了..... 不可能有下文了....

2006年离职,加入了现在的小公司,用了几个月做了一个很好的产品(至少我这么认为,无论是技术还是我对业务的理解),而且有2个用户在用,3个客户已经谈妥了。 好像公司可以很快步入正轨了。我也为自己的东西有人用感到高兴。

2007年3月,其中一个主要客户由于出现了股东变故,停止使用。而另外几个准备签合同的准客户都是这个主要客户的关系户,随着主要客户的停止使 用,他们3个客户也以各种理由拒绝签字。我们的业务突然间就陷入了困境。虽然我不管销售,但自己的东西没人用,总是感觉不好..... 他们在努力,努力,努力。。。。 但没有结果,1年,只开发了2个客户,其中一个还中途退出了。

我此时才认识到,技术无用论的来源。 你有再好的技术,如果卖不出去,等于垃圾。我在企业里安心的工作,努力的工作,结果呢?我已经被社会淡忘。对于一个30多岁的,没有名气的男人,我的出路在哪里?这段时间是我最难过的时间。

业余爱好者,学习JAVA在实际中有什么用途?

一个网友不是IT行业的,但是很喜欢编程,问到了我这个问题。

突然想起几个月以前另外一个银行工作的朋友,很喜欢编程,甚至想改行到IT,他已经27岁了,和我当初改行的年龄差不多。不过我是上大学就喜欢计算机,考大学因为差了20分没考上计算机系而已,学了化工,而且我改行前的待遇非常差。

我当时劝那个朋友,你有你的行业,而且是一个不错的行业,待遇很好(他自己说的),把计算机作为爱好还是有很多其它的方式展示自己的能力的。

下面是我当时回复的原文。

1 你为何爱好呢?为了证明什么?还是??

2 你爱好到什么程度?可以独立做一些东西了?

3 我想你从事的行业,一定需要你爱好的东西。相信我,不需要信息化的行业应该没有,而Java是很适合的一个选择。

你可以和你的同事谈谈,他们很可能需要一些技术机方面的协助。

我认为,能用的就是好的,
能用且好用的,就是精品。

记得新闻报道过,东北某个公安局的一个警员,业余时间自己做了一个管理系统,很符合实际需求,被全局推广了。我想,所有爱好计算机的,把IT作为专 业或者改行到IT不一定都是好的,大多数人作为一个技能,反倒是更能发挥它的力量。你熟悉自己的行业,又拥有了一定的IT技能,做出来的东西一定是精品。

希望此文对那些喜爱计算机,但不再这个行业工作的人有帮助。

请问JAVA要学会得要多长时间

一位网友问到的。我根据自己的情况,大致整理了一下

1星期,感觉啥都不懂,根本不知道在干啥
1个月,有点感觉了,好像不是那么难
6个月,我已经可以很熟练的干一些事情了,好像很简单
1年,发现许多东西不懂,看不懂,也没接触过
2年,发现不会的东西越老越多,有点迷茫
3年,发现跟不上了,而且学的东西,好多的用不到
5年,终于知道应该学什么了,不过也差不多该转行管理了

以后?我不知道,因为我才有6年的java经验

辞职日记----记录31岁的程序员跳槽心态

转载他的离职日记,有许多东西值得我们认真思考,人活着到底为了什么?

2008年6月26日 阴天多云 辞职前第16日

土耳其不争气,害的我输了近4000分的可用分,最为倒霉的是它尽然先进球,给了我那么多的希望。还有就是直播过程中突然的长时间的无信号,输都不知道怎么输的。

今天瞌睡比较重,上班的时候多睡了一会。下午到楼上抽烟的时候,遇到了一个做QA的公司MM主动和我打招呼,说今天是她在公司的最后一天,关键问题 是她认识我,而我不认识她,虽然在同一个楼层经常看到,也许是因为我是公司的名人吧,呵呵。随便聊了聊,她好像要去杭州的阿里妈妈,呵呵,据说工资很不 错。这年头,什么事情都敌不过一个字“钱”。

下班的班车上和以前同一个Team的同事坐在一起,他也和我抱怨原来的Team Leader不好,DM不好,我安慰他世界上没有绝对的公平,什么时候都要夹着尾巴好做人,我拿我失败的例子给他做了生动的讲解,呵呵。可是我也知道,程 序员都是一批有性格的人,也许我的教导对他来说收效甚微。

要离开公司了,今天开始整理自己的抽屉和桌面,把从公司借的书还了,把使用公司钱买的书移交给了同组的同事。不收拾不知道,竟然桌子上有5个喝水的 杯子,也许我是公司杯子最多的人了,呵呵,一个是我自己买的保温杯,冬天泡茶保温的,一次出差的时候买的;一个是公司发的喝咖啡等饮料使用的饮料机上使用 的杯子;一个是公司发的Cisco的杯子;一个是获得MSMVP时候搞的Microsoft杯子;还有一个是最近一直在用的紫砂杯子,老婆送的。一个杯子 代表我的一段历史,呵呵,看着这些杯子感慨无限啊,五个杯子代表我这几年走过的心路历程。

世界真小,今天在CSDN上竟然遇到了同一个公司的不同分公司的一个人。

最后,PHP虽然看起来很简单,但是要搞起来还是要几天的,明天继续PHP的学习。

2008年6月27阴天 辞职前第15日

西班牙没有让我失望,斗牛士们一直在创造奇迹......祝福他们能最终夺冠。 早上我以我明锐的观察力第一发现班车的到来,当别人还在傻傻的等待的时候,我已经快步的登上了更换为149路公交车的班车。 到了公司看到一个通宵没有回家的兄弟,正哈欠连天的看着电脑屏幕,这一切让我看到了去年年底一直到今年三月份的我的影子。那时候我也和这个兄弟一样,每天 晚上基本上都是两点以后从公司回家,每个星期至少有两天睡在公司。呵呵,那时候唯一的乐趣是就是在半夜的时候使用BT下载电影,那个速度就一个字快,最快 的时候达到过4M每秒。 经过两天的几乎通宵的熬夜,感觉实在是太累了。下午睡到快三点才起来,呵呵,反正现在没有人管我,那几个同个项目的兄弟开会也没有叫我了,伤感 啊......。起来看了看PHP的语法。 和几个哥们聊了聊物理,大家闲扯到底是走路比较容易减肥还是跑步比较容易减肥,呵呵,无结论,非物理学家。 快下班的时候收到两封mail,一封是通知钱伯斯要在下个星期一开All Hands Meeting,要求大家积极参与。其实和老外开会也挺好玩的,上次记得和两个也是非常高层的人开这样的会议,那两个老外简直是太“随和”了,在网络的那 一头放肆的开着我们中国人听不懂的玩笑。另一封mail是前台MM通知我去拿信件,说起前台的MM,那和我的关系不是一般的好,听说我要走了还有点恋恋不 舍,呵呵,虽然人家的儿子和我儿子同岁。前台的MM同时负责公司的考勤和办公物品的发放,由于关系搞的好,每每涉及考勤和相关的问题的时候,俺们组的那些 兄弟都是推选我去交涉,呵呵,也许我在走之前应该给他们留下一篇《怎么和前台MM搞好关系》,哈哈哈,上次和组里的几个兄弟一起去喝酒,回公司迟了,到最 后mail里面的统计的旷工记录,其他都在,就是没有我。 晚上带儿子去家乐福购物,儿子看着那些汽车玩具,就差流口水了,呵呵,俺就是一个字:你表现不好,什么时候得到了十颗星星了,就买给你。回家以后,突然觉 得自己有点残忍了,伤感啊...... 帮老婆搞促销资料搞到了12点。老婆当初看上我就是被我熟练的计算机知识所迷惑了,把我当作圣人一样崇拜,所以上我的贼船。老婆是个电脑白痴,除了会聊 天,其他都不会,让她学Word、Excel等等,她一概说看不懂,反正有我。我下次出去应聘一定在简历上写上:熟练操作Word、Excel!!!!

说说五个杯子吧: 那个保温的茶杯是我在第二家公司干的时候,在广州佛山出差的时候买的,那时候没有结婚,天南地北的跑,好不快活!!!每天激情不断,有时候半夜想到一个好 的idea的时候,立即起床打开笔记本干活,所以每次出差,同去的人都害怕和我同一个房间,简称同房。 当选MSMVP时候搞的Microsoft杯子,那时候我在Creative,在CSDN潜水很多年以后,突然不出差了,每天朝九晚五了,时间就多了,所 以很疯狂的回答问题,最后当选了MSMVP,150美金的购物卷,不知道买什么,随意买了几个made in china的玩具和杯子。 公司发的喝咖啡等饮料使用的饮料机上使用的杯子,那是WebEx股票大涨的时候,公司领导们良心发现,决定给大家提供免费的饮料和糕点,刚开始的时候使用 的是一次性的那种饮料杯子,可能是几天过后,领导们发现这个开销很大,所以每个人发了一个这样的杯子; 公司发的Cisco的杯子,那是去年夏天的时候,Cisco宣布正式收购WebEx的时候,给我们的所谓的“防暑降温”大礼包,其中还有一个无线鼠标、有 限耳机、鼠标垫、钥匙扣、笔记本(仅仅是纸质的),还有一个保温的包; 一直在用的紫砂杯子,是老婆送的,自从老婆开店以来,家庭收入明显提高,喝茶的档次也提高了,所以好马配好鞍,来个紫砂杯,呵呵,所以说我离开WebEx 也不是仅仅为了钱。

说起我的头像,那可不是一般的来历,那时候我买了一个山寨机,联发MTK的芯片,每天手写的发消息,那是下班的时候我正在给老婆发消息,我们组一个 专业的摄影哥们给照的,事后还PS了一下,当我选择它作为我Yahoo的头像的时候,几乎所有熟悉的MM都惊呼:原来PS可以这样强!!!弄的我很受 伤。。。。。。。。

我写这个帖子,主要想给大家正面的感受,伤感和忐忑是难免的,毕竟要离开一个熟悉的环境去适应一个新的环境。其实我想告诉大家的年龄不是问题,有时 候在我这样的年龄,大家都很伤感了,怀疑自己还能做多少年,我这篇帖子就是想告诉大家,心态比年龄重要,30岁以后的程序员应该活的更开心。

做程序,就精力来说,我觉得我能做到老,但是有没有必要做到老,有没有条件做到老,我现在还不知道。 楼主我不是搞PHP的,PHP只是我一时的兴趣,离正式离开公司还有一段时间,组里有一个PHP的高人,所以偷师学艺一把,呵呵,我才不“挥一挥衣袖不带走一片云彩”。

忠诚是很重要的一个特质,但是如果一味的愚忠,那就不好了。君不见愚忠的岳飞被奸人所害?愚忠的宋江最后被逼上梁山?小说也好,演义也好,很多时候这一切都是生活的缩影、影射。 我喜欢勤勤恳恳干活的人更甚于那种所谓忠诚却天天混日子的人。

女程序员确实在这一行业是被歧视的,我们要正视这个问题,也许这和女人的生理和心理有关吧。女人有生育的先天生理和后天产假政策保护,所以很多公司 不愿意为此买单,另外一点就是到了一定的年龄以后,尤其是有小孩以后,女人会更恋家,这样也会分散一点精力,但是我相信这只是这个行业暂时的缺陷,因为中 国的软件产业也还年轻,所以我们需要给它时间,用众多成功的女程序员的案例给它信心。 我见到过很多30岁以后的程序员、架构师、项目经理或者是这个行业的管理人员等等,要做到这一点我总结了一下,需要两点:第一点,必须要家人的支持,不可 否认程序员这一行业有时候压力会很大,有时候会暴躁,有时会封锁自己,更多的是加班,所以需要家人的支持和理解,这一点男程序员也一样。第二点,现在想做 到30岁以后的女程序员,要找一个大一点的公司,正规一点的公司,更多的时候担当一点领导者的角色会走的更久。

到了WebEx以后我基本上没有上过了,一是忙了,二是有小孩了,有时间多陪陪家人吧,三是年龄大了,有时候想静下心来思考思考。即使是现在,在离 职阶段,没有什么事情,我也只是偶尔上CSDN看看,基本上不回帖,除非特别感兴趣的帖子。 合理的时间安排其实是一个人成熟的标志,所谓的合理,一是有计划,二就是将有限的时间用在你觉得最值得的事情上。很多时候,程序员应该更多的在现实中交 流,网络永远代替不了面对面沟通。

呵呵,我从来没有觉得自己老,相反的,我觉得30岁左右应该是程序员开始成熟的年龄,应该是一个从积累到爆发的过程的开始。包括我在论坛上回答别人 的问题的时候,我也从来不说自己老了,更多的时候我只是说自己是“过来人”,套用一句周润发的广告语:成功是什么?我还在路上呢。 最近乐于解答一些人的思想问题,不涉及技术,不是冒充老人,只是这个论坛上有太多的年轻人,他们没有经历,所以迷茫;他们没有实践,所以畏惧;他们没有经 验,所以自卑;他们是我们这些先出来人的从前,是我们的青春缩影,是这个行业的未来,所以在空闲的时候我更乐意于为他们解惑,不是因为我说的都是对的,至 少是一种意见,一种参考,让他们多思考,让他们少走一些弯路,我看好这些年轻人,他们没有经历,所以他们可以无畏;他们没有实践,所以他们有无限可能;他 们没有经验,但是他们有青春的激情。

2008年6月28日 晴到多云 辞职前第14日

今天早上起来很早,发现没有什么不适,精神挺好。其实我也是一个和很多程序员一样喜欢在周末补觉的人,但是只要有事,一般早起还是没有问题的,所以说人的惰性是可以克服的。

把老婆的东西收拾好以后,送她出门去做活动,自己在家闲来无事,就上网溜达,发现盖茨辞职了,细看来,正确的说法应该说盖茨是跳槽了,离开微软去做 慈善这个行业了。很佩服盖茨能捐出自己的580亿美金的资产,一个人到了一定境界以后,想法果然不同。记得刚进WebEx的时候,一个牛人告诉过我,不要 抱怨自己的收入少,因为基本上每个人花费和收入都是成一定比例的,你收入高了,花费也会提高,不知道盖茨花费有多高?假如我是盖茨,我会怎么做?呵呵,感 觉很好玩,如果我是盖茨,我可能更“中国”一点,先孝敬父母,然后留点钱给儿女,然后帮助亲戚朋友,然后完成自己的梦想。什么梦想?就是“等俺有了钱,买 两个包子,吃一个丢一个”呗,呵呵。

儿子起床后,竟然很有礼貌的对我说:爸爸早上好!我和儿子起床总是有一个时间差,他每天上幼儿园,早上7点起床,走之前把我叫起床,呵呵。儿子痴迷 奥特曼,家里除了和奥特曼配套的车子、飞机、图书、碟子不算,光奥特曼就有8个。看了奥特曼以后,我们家除他以外的所有人都成了怪兽,他总是正义的奥特 曼,他身上的暴力成分越来越重,我和老婆为此揍过他不只一次,也和他沟通过,最近一次的沟通中,他说奥特曼是存在的,生活在宇宙中,我就问他,为什么四川 地震的时候,那么多小孩压在楼板下的时候,奥特曼为什么没有出现?儿子茫然很久,给出了一个答案。我觉得这件事和我在CSDN上看到的一个帖子很像,当众 多网友觉得他们需要MSMVP出现的时候,他们却没有出现,这时候“苍生”是应该责怪“奥特曼”呢,还是像我儿子给出的答案--“奥特曼睡觉了”呢?很多 时候我觉得给别人更多的宽容才是最重要,把别人往更好的境界去假想,也许可以活的像我儿子一样单纯而快乐。(相关帖子:http://topic.csdn.net/u/20080616/19/85e091cc-c78d-449d-834a-215ee504c02d.html

儿子和岳母出去玩了,我一个人在家无所事事,所以到CSDN上回答了很多的问题。又在这里遇到了一个公司另一个分公司的同事。感觉世界太小了,也许 是程序员的生活圈子太小了,也许是国内这样技术网站太少了,呵呵,这让我想到一个问题,类似的网站怎么能击败CSDN??其实很多程序员不懂得或者不愿意 去沟通,有的是技术保守,有的是有心无力,有的是这个行业造就的性格,我很庆幸的是我还算一个开朗的人,有很多朋友,一个几百人的公司,和我相熟的差不多 有一半以上,认识我的人几乎全部,认识我的人都是因为我做了一件“英雄”的事情而认识我的。

晚上被儿子 教训了一顿,他发现我将烟灰弹到马桶里面了,所以学着老婆教育他的办法,把我拖到他的房间里面教育了一顿。不过我感觉挺开心的,至少我儿子还是挺有原则的,不畏我这个强权,呵呵。

2008年6月29日 晴 辞职前第13日

天气很好,大晴天!较炎热。

今天带儿子去老婆做活动的地方,炮院。曾几何时,每每经过黄山路的时候,看见炮院威武的大门和神情严肃的卫兵的时候,我都觉得也许以后没有机会进去 参观参观了,因为觉得它肯定是守卫森严的,闲杂人等不得入内的,殊不知今天和儿子长驱直入,卫兵啥也没有问,呵呵,也许这就和我们编程时候遇到的难题一 样,咋一看,很难,很多人就畏缩了,悲观了,放弃了,殊不知也许仅仅只是一个消息映射,一个20行的函数就能搞定的。软件开发是一个实践性很强的行业,先 做足功课才能做出准确的判断,没有实践就没有发言权。我也曾经是一个容易悲观的人,每每遇到一个问题或者上面安排下来的一个任务的时候,我总是把困难充分 的放大,导致了在一段时间里,我总是觉得我自己很多事情都不可能完成,非常的悲观,后来我逐渐的意识到了这个缺点,现在要好多了。克服这个缺点就是一条: 不要总是活在以前失败的影子里!很多事情看似类似,其实不同,即使相同,随着科技的发展、自己技术水平的增长,原来很多做不到的事情,也许现在你可以轻松 做到。Just try it again!

中午带儿子去吃肯德基,吃完肯德基以后,我十分“残忍”的让儿子和我一起在烈日下直奔光大银行长江西路分理处(三里庵那),想办理到新公司的工资 卡,到了才傻眼了,原以为所谓的“分理处”至少应该比一个营业网点强啊,殊不知只是一个24小时的自动存取款的地方。再次证实:没有实践就没有发言权。光 大银行在合肥的网点真的是少啊,而且服务质量确实不怎么的,拨打了合肥分行的几个电话多次,均无人接听。无奈只好回家。回家上网google一下以后,我 变聪明了,逐个拨打他们其他营业点的电话,终于拨通一个,我报出我自己的位置,询问最近的营业点,才知道高新区刚开了一个光大银行,如果我仅仅按照 Google Map上提供的搜索结果,我可能需要跑到很远的地方,这样看来Google的服务也不可靠,所以建议google在其搜索结果上注明服务信息的更新时间, 并加上一句话“此搜索结果仅供参考”!

从毕业到现在工资确实涨了不少(我毕业的时候才700),涉及的银行也没有重复过,直接发现金--中国银行--工商银行--徽商银行--光大银行,搞笑的手里的两张信用卡却是交通银行和招商银行的。人啊,活着就是一种经济行为!

今天晚上欧洲杯,压了5005分,西班牙赢!只因更喜欢西班牙踢球的技术表现和那种艺术感,和做程序一样,很多人写的code像德国一样,虽然粗枝大叶,但是也能run,也能赚钱,但是我更喜欢那种看起来非常有层次感、条理清晰、读起来像诗歌一样的code。

天下没有不散的筵席,确实是离离合合不断。 我这个年龄离职时候考虑更多的是钱和环境、自身的房展等等,很多时候人都是想鱼和熊掌兼得,在我收到新公司的Offer的第一天晚上,失眠了,不是因为欧 洲杯,而是确实考虑了很多,现在所在的Team是我工作8年多以来遇到的最好的、最和谐的Team,也许是大家臭味相投,所以气氛非常的好,所以在公司很 多其他Team的人都羡慕我们,上次我们Team据说要招一个UI,殊不知首先是公司内部的三四个UI Developer都想过来。得知我要走,兄弟们虽然不舍,但是还是理智的支持我,我也肉麻的表白了一下:真的舍不得你们这帮兄弟啊。等哪天有空给大家说 说我们这个Team,说说那帮弟兄们,顺便做广告,招贤纳士。

2008年6月30日 晴 辞职前第12日

天气异常的晴朗,燥热。 凌晨西班牙获胜了,甚是兴奋。早晨在班车抵达前一分钟到达等候点。 一日无事,下午向HR的人询问了关于社保转移的事情,新东家的offer上说要有“社保转移单”,问了以后才知道合肥已经取消了这个东东,现在只要报社保 号就可以了。我觉得中国社会在进步了,本来嘛,没有必要搞的那么麻烦,像美国一样,一个Security ID或者是Passport ID搞定一切。

自从我提出辞职以后,我在公司已经是非常淡定的了,只有我们组的人知道,本想悄悄的出村,打枪的,不要。殊不知近来发现几乎所有的人都知道了,每个 人都知道我要走了,而且连我去的新东家都知道了,今天竟然有一个同事问我,新东家的HR的mail是什么,搞的我压力好大,呵呵。因为新东家就和现在公司 只隔一条马路,本来还想每天还坐现在公司的班车来上班,省的跑老远的坐公交车,现在看来泡汤了,呵呵。

下班前那个给我拍头像的同组的兄弟说:你要走了,临走我准备给你拍一个短片给大家留作纪念。他发给我的剧本如下: ================================== Max 拿把剑, 站着, 很挺拔。

慢慢抽出剑

抬眼说:

“我的对手一定看不见明天的太阳”

镜头摇开,

原来对面站个人B(寻找演员中), 手里也拿把剑

B也慢慢抽出剑, 低头根本不看人, 看脚趾,缓缓道:

“天气预报明天是阴天!”

场景摇开, 原来是某某决斗场! 观众全倒! ================================== 我们在yahoo上的对话片段: 我:好的,先把我的片酬拿出来请我们Team的人吃一顿就可以了。 他:好,你先让我潜规则一下你! 我们组总是充满着这种搞笑的气氛,不过大家干起活来还是一丝不苟的。

这段时间,下班回家的时候将自己留在公司的书一本一本的搬回家,今天搬的是潘爱民翻译的《深入解析Windows操作系统》。我这个人爱收藏书,尤 其爱收藏自己认为是好书的书。曾经千辛万苦的搞到一本《Windows 95程序设计》,现在最想收藏的就是袁峰的《Windows图形编程》。

网络流行的今天,很多时候很多资料都可以在网上找到,但是我依然喜欢那种抱着一本书,一页一页的翻看的感觉,尤其是那淡淡的油墨香味。在这个快餐的 时代,很多资料在网上找到,有时候我们宁愿在自己遇到困难的时候Google一把,也不愿意在闲暇的时候去好好读一本书,就纸质的技术书籍来说,它有很多 好处,最大的好处就是能让你系统的学习一方面的知识,至少比在网上google出来的一段代码教会你更多东西。所以我建议大家有空多读读书,也不是一定要 看技术类的书,看看其他有益的书也是可以的,前段时间看过《世界是平的》,感觉不错,推荐。只是现在的书是越来越贵了,呵呵。

我的英雄事迹,呵呵,说起来不好意思啊,当时我还没有现在这么淡定。去年公司开All Hands Meeting的时候,美国老大在台上说的什么公司股票涨了、Cisco收购了我们了、人民币升值了,前景一片大好,生活水平会上升了。说了整整一个下 午,最后提问的时候,我站起来说:首先我要纠正EEEE的一个错误,人民币是升值了,但是我们不可能拿着中国的钱到美国去花,中国的物价飞涨,我们的钱应 该是越来越不值钱了,猪肉都十几块钱一斤了。随后我给他举了一个例子:2005年的时候我进公司,过节时发了两桶色拉油加上六听一打的可乐,标准是100 元每个人,今年如果以这样的标准,我们连两桶色拉油都买不到。搞的老大很被动,辛辛苦苦说了一下午,被我这一个问题给搞砸了。当时老大就承诺给我奖励一瓶 美国加州的红葡萄酒。今年他再来开All Hands Meeting的时候,还特意搞了一个颁发红葡萄酒的仪式,所以说基本上公司的人都认识我。 现在领悟了:穷则独善其身,达则兼济天下。高调做事,低调做人。2007年我给我们Team留下了两个词:低调,淡定。

2008年7月1日 晴 辞职前第11日

今天的主题是“改变”。

今天是党的生日,共产党改变了中国;今天也是香港的生日,重生的生日,11年前的政权的巨变。

今天在看《Head First 设计模式》这本书,实话实说,曾经也看过《设计模式》这本书,还是电子版的,觉得没有弄的太明白,这次刚看了几页《Head First 设计模式》,我就爱上这本书了,尤其喜欢其中的插图,这本书中的例子也是通俗易懂的,呵呵,虽然是Java的例子。改变一下表达方式,也许同样枯燥的东西 会人不同的感觉。

中午和哥们一起出去喝酒的时候,接到了新东家HR的电话,通知我提前一个星期去报道,也就是下个星期一去报道,因为他们那边的新的应届毕业生也要来 了,我正好和他们一起培训。我辞职的计划被打乱了,还好,我有很多的加班假可以调休。这一切就象软件开发一样,软件开发永恒的主题就是:改变!很多人在做 的事情就是在已有的code上不断的Change,这个行业如果能从头自己完整的开发一套大的系统,虽然可能比较辛苦,但是绝对是一个幸福的过程。改变会 带来很多的风险,抵御风险的是有更多的“调休假”和自身的改变,也就是在计划的时候将change带来的风险估算上、灵活的change自己的计划。我曾 经做过一个项目,需求的change带来的计划的change远远比本来设想的大,到最后弄的自己身心疲惫。我个人认为在做项目计划的时候一定要预留 30%的Buffer,否则很多项目都会delay,甚至被Cancel。

公司从5月份开始安排的旅游计划一拖再拖,今天终于给了一个相对比较肯定的答案,这个周末可以出行了,但是由于下个星期一要到新东家去上班,所以我 还是决定不去了。如果这次旅游对我来说是一个项目的话,那么这就是由于提前到新东家上班和旅游计划delay双方面的作用,导致了这个项目的失败,也就是 说做项目的时候不仅仅要考虑自己目前的这个项目,有时候相互依赖的项目同样会导致项目的失败。

总结陈词,这个世界就是一个改变的世界,当你发现自己的缺点的时候,你需要改变自己适应这个世界,当改变来临的时候,你要学会怎么去应对它。以不变 应万变,不变的是你的信念和信心;以改变应万变,改变的是的缺点,永远要使自己在进步中。善于发现改变,善于自我改变,善于应对改变的人就是人才。

2008年7月2日 阴转晴天 辞职前第10日

今天到公司才发现昨天来了不少新人,我边上坐了一个新来的小伙子。他一脸的阳光和兴奋,我仿佛看到了八年多前我的影子,从学校走上社会的那种新鲜感 无法克制的表露在脸上。我心里在想,不知道他是否也会和我一样,在八年后看淡看穿这一切。年轻人就象一张白纸一样,很多时候,第一个公司和自己的态度决定 了这张白纸会最终画成什么样子,最主要的还是自己决定了方向。这个小伙子做得另一件事情,也让我觉得年轻就好,年轻可以有无限的冲劲和大胆。公司是不准使 用迅雷和BT等等的,也许是小伙子看到我安装了迅雷,所以就下载迅雷来安装,要知道我是公司里面为数不多的可以使用迅雷和bt的人,其他人的端口都封了。 我没有告诉他,因为我觉得等有一天他自己发现了再问起来,也许会更好一点,印象会更深刻一点,另外我喜欢积极主动的人。

早上走的时候下着大雨,所以带了一把伞,下午回来的时候是晴天,就忘了把伞带回来了。有时候生活中的其他事情也一样,换了一种环境,你能忘记一些东 西,最好是忘记一些不愉快的、不积极的东西。昨天晚上看了帖子中的很多人都会觉得辞职是一种无奈,其实为了生活、为了糊口也好,为了精神上的东西也好,辞 职确实让人有点不舍和忐忑,但是从积极的方面看,辞职所带来的是家人生活质量的提升和自己心情的改变,这就是积极的,何不多想想积极的东西。舍得,有舍才 有得。注意这个词,要先有所舍,才能有所得。

晚上和儿子吃饭的时候,儿子一直在问我关于我小时候的事情,是否有零食吃?是否有肯德基?是否有......,紧跟在这些问题后面的是,为什么?我 不知道怎么给儿子解释当时为什么是那么种状况,太深的东西儿子无法接受。不管怎么说,我觉得今天我所做的一切都是值得的,至少让儿子过上比我小时候幸福的 生活。一个人做很多事情的时候都有一个价值的衡量过程,如果他觉得值得,那么就会为这个精神支柱或者是所谓的理想,而觉得幸福。辞职也一样。Follow your heart!

2008年7月3日 晴天 辞职前第9日

今天早上起的非常早。早上5点多一点,儿子做噩梦被惊醒以后就没有睡觉了,我也就起来了。儿子梦到被飞机追,吓醒了,呵呵,奥特曼看多了就是这样的结果吧。

今天早上抽空去了派出所一趟,把儿子的户口迁了。以前,在感觉就是这一纸所谓的集体户的户籍证明,让我始终没有一点安全感,觉得自己在流浪,在漂 泊。我想这也是很多很多程序员在异乡拼搏的时候的一种感受。其实真的买了房子以后,自己倒是懒得去迁户口了,到新东家之前,把户口迁了吧,否则害怕到新东 家以后没有时间了。以前的一个朋友告诉我,进入一家新公司,第一年你要把自己不当人,呵呵,感觉说的过了,但是确实要认真一点。

中午去食堂吃饭了。自从到了现在这个Team,已经很少去公司食堂吃饭了,基本上每天中午都是到外面的饭店喝酒。说起来明天是我辞职前的第八天,其 实也是我在这个公司的最后一天了,因为从下个星期就要到新东家去上班了。这边也就是到下个星期五来办理一下手续。公司的食堂,中餐的供应商也是在这么多年 来走马观花的替换着,打好了饭菜突然没有了食欲,也许是伤感吧。虽然公司午餐的标准是一再的上升,但是饭菜的质量却是这么多年以来不断的在下降。我见证了 公司从使用就餐卷到刷卡就餐的这个过程,见证了公司不断提高就餐环境的过程。往事一幕一幕啊......

下午组里的Team weekly meeting,也是我最后一次参加这种会,去了,两分钟以后,又回来了。留点回忆吧。

下午QQ上遇到了以前一起在CSDN抢分的“小疯子”,他现在人在上海。怀恋那时候CSDN的疯狂。狗狗、陌生人、小疯子等等。

下班了,一早来到公司楼下,看着公司前面停着的一排私家车,让我想起网上曾经有人发帖问,有多少程序员能有房有车?就我看来现在的公司应该有10% 的人是有房有车的,其实比例是挺大的,所以说做程序员也是一份不错的职业,虽然不像一些人说的是白领,但是一定要乐观,如果自己都对这行没有了信心,那么 我觉得很多时候,如果自己还年轻,最后离开这行。

2008年7月4日 晴天 辞职前第8日

今天其实是我在现在公司的最后一天了。Yahoo Messenger上挂着“Last Day”。

早上到公司检查mail,发现公司HR要求等级工作年限的调查。从只要求等级英文名,可以看出这只是合肥公司的内部调查,我想公司应该是想对一些老 员工或者是工作时间较长的员工做一些“政策”上的倾斜吧。不是妄自尊大,我想这样的调查和我的辞职应该有关,不是说我是非常重要的人物,其实在比较大的公 司里,一个人再怎么重要,也不会对全局产生什么影响(所以我依然看好盖茨“跳槽”后的微软)。公司做这样的调查我想是因为我提出辞职以后和HR的人谈的时 候说的话有关吧,我不像别人的人都说一些冠冕堂皇的话,我一针见血的指出了公司现在对待有丰富工作经验和有能力的人的“政策”上的不足,反而让一些刚毕业 的学生拿着比为公司奉献了很多年的老员工还高的工资。我虽然辞职了,但是我依然希望现在的公司能越走越好,如果我的辞职能给公司一个警醒,让公司发生一些 改变,我想我的辞职会更有意义。

一个公司的制度和机制的成熟应该是需要一个时间的,所以在公司发展的过程中难免会有一些制度上的不足,那种绝对的公平和平等都是理想的,程序员,这 一特别的群体,多多少少保持在学校时候的单纯和理想化,所以很多时候无法接受这些,很多人在一气之下选择了离开,昨天遇到的小疯子就是这样。其实多走上社 会看看社会的复杂面,你会发现这一行业还算比较干净的。我经历过好几个公司,各种类型的,大的,小的,国有的、外资的,没有一个公司能百分百的让我满意, 每个公司都有不足的地方,所以悲观的说,天下乌鸦一般黑,稍稍乐观一点的就是:生活就是这样,我得学会改变自己去适应和接受它。这个社会已经没有人能做到 “一心只读圣贤书,两耳不闻窗外事”了,很多人喜欢把自己所在的公司和别的公司比较,但是人往往做的都是将自己公司的短处和别的公司的优点相比较,一旦真 的进入了那个公司不见得就会感觉很好。距离产生美,也许有一天他也会和新公司“因为熟悉而分手”。所以辞职需谨慎。

开始清理机器中的文件了,每见到一个熟悉的工程,总是打开看一看,回味一下,然后就是很多熟悉的code一行一行的在我眼前消失。不仅仅是公司产品 上现在的code,更为舍不得的是那些我觉得非常有意义的我修改的公司产品的code,虽然它们最终没有被老大们采用。那些测试工程的code基本上一看 到名字就能回味其当初的日子。还发现了很多以前从网上下载的还没有来得及看的电子书和一些例子程序。删除这些东西的时候,每按下一次 Shift+Delete,仿佛就像删除我一段记忆,伤感........

开始将我抽屉和桌面上的文件整理了一下,今天特意带了一个袋子来。讨论Design时候的草稿、和公司签署的合同、保密协议、公司的员工手册等等。 抽屉里面最多的是信用卡的账单,呵呵,辞职了要改的东西太多了,信用卡邮寄账单的地址要换了,信用卡的电子账单的mail地址要换了,很多论坛和网站的注 册mail地址和通知mail地址都要换了。包括CSDN上的注册邮件地址和邮寄地址也要换了。呵呵,工程不小。

下午,在Yahoo Messenger上和以前的Team Leader聊了两句,问了一个压缩文件的密码。我和他是因为一件事情闹的很不开心,这件事情多少和我选择离开现在的公司有一定的关系,我和他已经一年多 没有说话了,虽然经常面对面的碰到。当时他给了我一个压缩文件,里面是一封邮件,说他当时之所以那么做的所有原因都在那个压缩文件里面,设置了密码,说等 到有一天我们其中一人离开公司的时候再打开看看,我想今天是时候了,呵呵,其实不用打开我也能猜测到其中的内容,打开以后果然如我所想。不惊奇,仿佛此事 与我无关一样。其实真的离开的时候,一切都看的淡了,相逢一笑泯恩仇。有时候人在职场,在不同的位置上所做的决定也是不同的,学会理解别人吧。

A:呵呵,压缩文件是一封mail,邮件的背景是我在春节前提出请假,农历腊月28开始请两天,当时我是Task owner,也就是一个项目的头。公司规定请假的条件是7天没有bug,我已经是连续13没有bug了。因为当时我让Team Leader在请假条上签字的时候,他说由DM(部门经理)和老总签字就可以了。快下班的时候,我让DM,签字的时候,他正在忙,所以让我把请假条放在他 的桌子上,他签过字以后会找老总签字。所以我发了mail以后离开了公司。

邮件由我开头,我的内容是“我将于明天开始请假,我明后两天依然会在合肥,我的手机号码是:XXXXXXXXXXXX,相关问题已和项目的成员交代 清楚,24小时开机”。发送给我的DM和Team Leader。DM回复邮件询问了Team Leader是否准假,Team Leader回复邮件不准假。然后DM就将邮件抄送给了老总,表态不批准我的假,老总回复mail给我和所有人,要求我第二天继续上班,然后去掉我以后, 发送给DM和Team Leader,说如果明天我不上班,就把我的年终奖扣掉并且解雇我。 压缩文件的内容就是这样,Team Leader一直以为他第二天通知我来上班是解救了我,但是也请大家想想,最初的源头是谁挑起的?至于事情后来的发展就是,我在第二天上班以后,在老总的 办公室和老总拍着桌子大吵了一场,然后把DM和Team Leader都叫来对质,但是老总在明知道DM和Team Leader有错的情况下,依然护着他们,后来就是我工作到了年三十,拿到了年终奖,没有被解雇,第二年换到了另一个部门的另一个Team。

2008年7月5日 晴有雷阵雨 辞职前第7日

现在窗外还有闪电,雨点很大。

今天早上开时和老婆一起出去做活动,酷暑难当,期间还和老婆跑了一趟国美,买了一台空调,大大的柜机现在就摆在客厅里,现在的商家啊,那个办事效率 就是高,中午十二点多买的,5点多就给送到家了,明天安装。商业上竞争和软件业一样,同一种东西有很多的品牌,空调有海信、海尔、三星、三菱、格力等等, 同样软件业中杀毒软件有卡巴斯基、瑞星、江民等等,竞争非常残酷,所以如果是创业,一定要有一个非常与众不同的idea,做一个非常与众不同的东西才能胜 出,那些有关系、有背景的创业者不在此列。空调各有各的卖点,软件也是一样,走别人走过的路很难走的很远,很难走出新的东西。其实竞争无所不在,在我现在 的公司,做Web这块的主要有合肥和印度,就是同一个公司,有时候也需要为同一个项目进行PK。

我已经开始为到新公司工作做准备了,今天在做活动之余,借了老婆朋友的一个电动自行车试了试,很久没有骑过车了,大学毕业以后就将在学校里的那辆二 手自行车给卖了,呵呵,还是卖给当初卖给我的那个人,落叶归根了,呵呵。刚骑上那辆电动自行车的时候,还真的有点不适应,两圈以后,感觉好多了,耳旁呼呼 的风声,仿佛让自己回到了大学时代,一下子年轻了很多。

晚上吃过饭,正在网上闲逛,接到了一个以前同组同事的电话,他是去年年底离开公司的,住在我家前面的另一个小区,可能也许也是最近比较迷茫,打电话 约我出去聊聊。这个哥们技术相当的好,也是非常有个性的一个人,曾经在酒后大骂了我现在部门经理两个小时,当时我就在旁边作陪,随后我们经理还开车把他送 回家,我又作陪,呵呵,在车上,我们经理让我看到了一个男人的胸怀,说了一句非常经典的话,我至今记忆犹新,“XXXXX,你使劲骂,你骂的越多,我越清 醒,开车越稳。”。男人就应该有这样的胸怀,开自己的车,让别人去骂吧,呵呵。

这个哥们离开公司以后,自己创业过,但是不是很顺利,现在在一家电脑学院当管理者,现在又想去阿里妈妈,呵呵,他脑子很乱,想找我参谋参谋。根据他 的性格,我劝他如果是去阿里妈妈,那么一定要当个Leader,否则别去,多少钱也别去。他是一个孤傲的人,朋友很少,个性比较强,这样的人适合当 Leader,如果是当“小兵”,我怕他走不了多远。同时我也让他多学会低头,有才也不能恃才狂妄,很多时候成功的人还有一个特性就是耐心。

2008年7月6日 晴有雷阵雨 辞职前第6日 早晨早起,逐渐在改变自己的生物钟,以适应新东家的作息时间。

中午时分,装空调的来了,安装的很顺利,一切都好。人走后,使用了约半个小时,空气开关跳闸,以为电流过大,关闭家里的大功率电器,其后还是有跳闸 的现象,打电话给装修公司和水电工,都说不知道什么原因,老婆除了愤怒就是一脸的无奈,这时就发挥了我做计算机的优势,上网,google一把,发现其他 人也有类似情况,就是在小功率下也跳闸,归结的原因就是空气开关坏了,需要换个新的。Google有时候确实很有用,不仅仅是在工作上,同时在生活上也是 一样有用。其实本质是网络发展带动了知识的共享,很多时候,我觉得大家都应该有这种知识共享的精神,不仅仅是生活上的技巧,工作中技术上的知识共享肯定同 样会让自己进步。

今天晚上的F1比赛让我感触颇深。F1是一项激烈的运动,超车这种情况,往往只会发生在转弯时,因为在直道上各个厂家的赛车其速度基本上是相同的。 生活中一样,在一帆风顺的情况下,在万事俱备的情况下,其实大家都是没有区别的,就是在困难中、逆境中,才能分的出胜负和高低,此时如果你能在心理上、技 术上超过别人,你才是真正的强者。F1的团队精神同样值得学习,很多F1的技师做的活只是换换轮胎、加加油、调整调整风翼等等,这些看似简单的工作,其背 后有太多的技术和经验的成分,其在很多时候都决定了一个团队的成败。所以很多时候我们也要甘于做幕后的黄牛,让团队中的“车手”在前台风光。如果人人都想 当“车手”去风光,那么这个团队就不存在了,就注定要失败。还有,记得一次见到加油的技师没有能及时的拔掉加油管的配合失误,这样的情况在我们的生活中、 工作中,我们的团队中应该也会出现,这时候我们应该怎么看待我们身边的“失误的加油技师”呢?想过以后再想想,如果我们自己就是那个“失误的加油技师”又 会怎么样呢?

明天就要到新东家去报到了,呵呵,晚上在准备一些东西,收拾好了放在床头。我想这也算我的一个好习惯吧,永远要想着明天,为明天做好准备。看过一本 关于海尔的书,介绍了海尔的“日清”工作法,就是每天下班前抽一段时间总结一下自己今天的工作,准备一下明天的工作,写在纸上,罗列出来。往大了去看,如 果不是只准备明天的事情,而是准备自己未来的五年或者是十年的工作目标呢?想想吧,反正自己也不会因为思考这些东西而失去什么!

2008年7月7日 晴有雷阵雨 辞职前第5日 新公司第一天

今天是七七事变的31周年,铭记国耻,发奋图强。

早上还是和以前一样早的起床,同样的还是做原来公司的班车去上班。呵呵,我还没有算离职,还有一些东西要去公司拿。到原来的公司拿了一些东西,来到 了新公司。在前台遇到很多刚毕业的学生,大部分是安徽的或者老家是安徽的,也有几个是外地的,而且很远。年轻人就是活跃。大家相互打听着租房、学校、专业 和在新公司所在的组。九点多的时候,我给HR的人提交了一些资料和证件以后,和四个刚毕业的学生一起被另一个人带到了六楼。去领机器的时候才发现,其他的 人都有机器,我的机器还没有到,估计明天才能到。领了本子、垃圾桶等等东西以后,回到座位,感觉很茫然,不知道要做什么。

同学和以前的同事都过来打招呼,聊了聊,出去抽了支烟。一晃中午吃饭的时间到了,以前的同事邀我一起前去,从六楼的楼梯一路奔驰到一楼的食堂。人很多,排队、打饭,饭菜尚可,不禁和以前的公司比较了一下,应该该觉比原来公司要好点。吃完饭,回到座位上开始睡觉。

一点多点的时候,到了抽烟的地方去抽烟,看到了一个看起来就是领导样子的人,不知深浅,未交谈。回到座位上,HR的人打电话要我过去一下,将体检报 告送过去。回来的时候,正好遇到了刚才一起抽烟的人,他直呼我的名字,让我惊讶,让我一起去开会,新来的那几个学生一起。果然不错他就是合肥这个部门的 DM,介绍了台湾过来的人,大家自我介绍一下,介绍了在公司的工作任务和目标。散会以后,回到座位看书一直到六点下班。

这是毕业这么多年以来,唯一的上班时间没有电脑的一天,基本上看了一天的书,还算习惯。对于外界对现在公司的反面的传闻,也没有体验,感觉同事之间气氛还是比较好的,只是工作环境过于安静。因为没有机器,所以晚上没有加班。

今天有一件事情让我觉得刚毕业的学生需要改进的地方,因为座位上没有插线板或者是少了一根电源线,所以那几个学生就一直在座位上等待,等别人来问为 什么没有开机,等别人来帮助他们解决问题。我觉得这一点非常不好,不管是刚毕业的还是工作了很多年的人,主动是很重要的。当问题发生了,自己应该先去尝试 解决问题,解决不了的,可以向上级报告问题,寻求别人的帮助,而不是消极的等待。其实这个问题很好解决,只要去刚才领机器的IT部门领一根电源线,或者是 领一个插线板就可以解决了。我告诉了他们,他们中的某些人还是坐在座位上等待,让我很失望。

2008年7月8日 晴有雷阵雨 辞职前第4日 新公司第二天

今天早上从原来的公司将几本书和靠枕带到了新的公司,坐起来舒服多了。从老公司下楼的时候遇到了一个哥们,没有同组过,但是关系不错,同校且同届, 他的目 光中多少有点诧异,也许他觉得好日子来了,我不应该离开公司吧(Cisco正式合并已经要完成,福利会有所提高),不管怎么说,在这个时候离开也许在很多 人眼里都是不明智的,但是每个人有每个人的考虑重点和衡量准则,所以在很多时候别人的意见只是一种参考,不同的背景、不同工作性质,不同的人总是有不同的 见地,要多听多思考,而不是被别人所左右。

早上还是没有机器,所以在看书,看汇编,做嵌入式的东西,汇编有时候有意想不到的好处。台湾的老大看看了,没有说什么。临近中午的时候,在抽烟的地 方遇到 了DM,问起机器的事情,如实回答,还没有。抽完烟以后,公司的IT,忘了告诉大家了公司的IT是个MM,立即给我找了一个闲置的机器,也许是老大觉得给 我这么高的工资而让我闲着太划不来了,呵呵。拿到了机器以后,开始装机、配置开发环境,连接管理系统,查看公司资料,回复相关的mail等等,开始忙了起 来。

下午发生了一件事情,公司的考勤系统mail通知我们这些新来的人,昨天的考勤不正常,只有下班的记录,这是因为我们是在九点以后拿到的考勤卡,所 以基本 上没有人去刷卡考勤。这时候,刚毕业的学生再次显示出经验的不足,为了这个mail在商量了很久怎么处理,是找前台考勤的呢,还是找DM呢,在他们商量的 时候,我就直接将mail转发给了DM和HR让他们帮我证明并解决这个问题。很快DM给了回复,让前台的考勤MM直接修改记录,问题轻松解决了。其实很多 时候,解决一个问题时候要学会使用手边的工具,不仅仅是开发的IDE,Mail、IM和电话都可以迅速的帮你解决问题或者是帮你找到解决问题的人。选择合 适的工具同样是一种技巧。

有时候还要学会怎么去找到自己想要的资源,比如在公司中的域中有很多映射的网络盘,上面有很多的资料,我看到的几个人是一个一个目录的去找,我的办 法很简 单,直接使用Windows自带的搜索功能,查找关键字,如“模板”、“WinCE”等等。还有在进入一个新的环境的时候,有时候张张口问问其他人所获得 的信息,要比自己摸索很长时间得到的要多得多。那种刚踏入社会的羞涩,应该在进入工作环境以后,迅速的改变以适应今天这种高速的、竞争激烈的社会。

晚上加班了,主要是安装工作机上的软件。回来的路上一人在昏暗的路灯下走了很远的路,有点不习惯,有点落寞的感觉......

2008年7月9日 多云 辞职前第3日 新公司第三天

今天是对我来说真正意义上的新的工作开始的一天。从今天开始需要完成有目的的东西了。下午Team Leader给我们开会,比较详细的介绍了我们需要完成的各个任务的细节。简单的一点说就是现在将要做的将是我从来没有接触过的,以前做的最底层的也就是 WinCE下的软件开发和简单的WinCE的裁剪,现在好了,我要做WinCE BSP了,呵呵,所以今天MSN上挂着的口号是:My life, Reset, Refresh.因为现在的Team Leader是一个台湾人,他的普通话不是很好,加上台湾的一些计算机名词和大陆这边有区别,所以就是夹杂着英语和大家说,简单的英语对我来说应该还没有 问题,加上读过一些侯捷的书,台湾的那些计算机名词也还能接受。但是刚毕业的学生就难了,显得很茫然,很多时候我从他们的表情就知道他们根本没有听懂老大 在说什么,所以在会后我给老大提了一个意见,说慢一点,将一些特殊的英语缩写在PPT中写出来,会后将会议的PPT发给大家,下次开会找一两个老员工做“ 翻译”,这样可能在前期刚接触时候的沟通上会顺畅一点。学会增加或者改进沟通方式,也是人生的一条重要技巧。

下午开始安装WinCE和相关的开发软件,熟悉熟悉,下个星期开始将有一个从台湾来的同事给我们做培训,呵呵,据说他是MS在台湾授予的唯一个 Windows CE的MSMVP。Team Leader给我们组里面一人买了一本Windows CE嵌入式的书,据说这两天就到。同时这几天我也在看Online MSDN,才知道英语的重要性,关于嵌入式的书籍,尤其是WinCE的书籍,中文的实在是太少了,现有的很多也是在MSDN中截取、翻译而来。现在看 MSDN还有点慢,不过相信过段时间就能越来越快了,感觉学好英语很重要。

今天犯了一个错误,呵呵,使用Platform Builder裁剪WinCE内核的时候,由于没有关掉杀毒软件,导致在build过程中中断了。竟然一时没有想到是什么原因,后来找来老员工才解决掉。杀毒软件引起的问题,其实非常常见,哎.......

2008年7月9日 多云 辞职前第2日 新公司第四天

今天上班开始就在搜索相关的WinCE BSP的资料,很忙也很累。一直在思索一些问题,因为到新东家以后要做WinCE中最为底层的东西了,和我前8年多时间做的东西基本上没有太多的关系了, 直接是硬件上的东西,甚至直接是硬件了,感觉放弃了这么多年来的积累,思考着是否值得。我想很多跳槽的人都有过类似的经历,觉得换了一个环境,放弃了一些 积累的经验,有点彷徨。今天我想明白了,我决定留下来,认真的做好现在的这份工作。有以下几个原因:

1、足够新的东西会给我足够多的挑战和激情。也许我可以一直做Windows PC上的应用程序(今天还有人给我打电话,问我是否可以到他们公司谈谈),我可以做到Perfect,但是也许有一天,我会厌烦,如果每天重复的做同样的 工作,那么也许自己会失去激情,行尸走肉。人都是希望能有点新东西来充实自己的,只是真的这样的机会来临的时候大家都有点害怕和惶恐。就像那些没有出差过 的人,一定会想有机会出去出差一次,但是真的让他们出差的时候,也许会考虑很多问题,怎么坐车?怎么住宿?怎么和客户沟通?会遇到什么难题?

2、新的工作方向的未来发展趋势很好。我觉得未来的世界将需要更多的嵌入式的产品,也就是需要更多的嵌入式的开发人员。互联网的普及造就了信息沟 通、知识分享的广泛应用,我相信未来嵌入式的产品将在家庭生活、工作娱乐等等方面上带来更多的便利和乐趣,将是互联网的一个有力的扩展和补充。

3、我觉得自己以前的经验没有完全被丢弃。这8年多了,除了Windows PC上的应用程序开发的经验,我还学到了怎么做事的经验,怎么解决问题的方法,怎么思考的方法,怎么去控制项目的风险和进度等等,这些东西依然会在我今后 的工作中起到作用。这也许就是新东家为什么看中我的原因,也许是新东家让我做这块的原因,可能他们认为我在这样的一个Team,能帮助那些刚毕业的学生们 尽快成长起来。

4、这是新东家在中国大陆真正意义上的一个研发Team。新东家的硬件设计好像都是在台湾完成的,公司其他的Team基本上都是做着为硬件服务的项 目,也仅仅是项目而已,我们将要做的是一个平台,如果做好了,公司的其他的很多项目都将在我们的平台上进行开发。Team Leader也告诉我,总部对这个Team很重视,从总部安排人过来进行针对性的培训就可以看出来了。问了很多老员工,确实他们在入职以后,只是经过合肥 本地的培训。我觉得在这样的一个Team做出来的事情更有成就感,得到认可的感觉会更强烈。

5、公司的成长前景也是我考虑的一方面。新东家这几年的成长速度很快,而且对员工的福利也越来越好。新东家的产品定位、技术能力、市场前景都很好,未来肯定能发展的更好。

其实做事谨慎是应该的,但是如果一味的保守和畏缩,可能使自己丧失很多的机会。虽然也许在很多人看来我已经不年轻了,但是至少我还努力的想让自己走 的更远、更好。我都如此,我想那些比我年轻的人,更需要大胆的创新和尝试,不仅仅是在跳槽上,工作上也是。前段时间余世维(非常出名的讲师)给以前公司的 同事培训的时候说过,要多听多看多思考,我觉得还应该加上,多尝试。

2008年7月11日 晴天 辞职当天 新公司第五天

早上按时来到公司,一切都和往常一样。

因为下午要去以前的公司办理辞职交接手续,所以需要请假,和Team Leader谈了,他爽快的同意了,通过OA系统填了请假条,迟迟不见他批准,心中有点忐忑,感觉自己得了“请假综合症”了。一会自己上OA系统查看才发 现已经批准了,只是请假在OA系统中没有邮件通知功能。

11点左右,HR的人打电话让我去签合同,看了看就签了,当即HR就给了我一份。回到座位上还没有坐下,Team Leader就找我,要和我好好聊聊。我们俩在一件Office里,坦诚不公的对组里的情况进行了交流,Team Leader也对我以往的工作经验进行了十分仔细的询问,对我在这个组中的作用,提出了很高的希望,我也给他提出了一些建议和想法,大家基本上达成了一致 意见,气氛十分友好。

吃过中饭来到了以前的公司,以前Team的兄弟没有惊奇,寒暄、抽烟以后,我找到HR,打印了一份辞职报表以后,和HR的人聊了很多,他们都关心我 那边新东家的情况,呵呵,如实告之。开始找相关的人签字,期间抽空回到座位上将机器整理整理,删除了mail和QQ的聊天记录等等。Yahoo上不断的弹 出公司里人的询问和祝福,这一点至少证明我在公司还是人缘不错的。找了财务证明没有借款、Office交上工作牌、DM交接工作、IT交上工作机器,在所 有人都在那张辞职报表上签字以后,一身轻松的来到HR的办公室,交上辞职报表以后,换来了HR开出的一纸解除劳动合同的书面证明。在看着HR盖上红红的公 司印章的那一刻,有点伤感,三年多了,现在真的是一点点关系都没有了。同一个包里同时放着离职证明和工作合同,借用周星驰的一句话:人生的大喜大悲总是来 得太快太突然。其后在座位上吃着西瓜喝着南瓜汤,等着下班,因为Team Leader刚从US回来,晚上请大家吃饭。

晚上的酒桌上大家推杯换盏,畅所欲言,在我几两白酒和两瓶啤酒下肚以后,老婆打电话要我回去,家里有事。在单独陪Team Leader一杯以后,倒满了,大家主动的站起来为我送行,一口干了那杯酒以后,迅速的拿起包想要离开,气氛太伤感了,Team Leader从后面追了上来,搂着我的肩膀,将我送到门口,其间说了一句话:不管怎么样,不管在哪里,一定要过的开心。心中十分难受,无言,冲出门外,钻 进出租车,一路疾驰而去.......不敢回头~!

辞职总结

经过这么多天,思想波动、感情折磨,辞职真的是结束了。总的来说就辞职这一点有以下几点想法:

1、辞职是件幸苦的事情。有时候为了追求更好的东西,人往往需要克服自己的惰性,先舍弃一些东西才可以。往往有很多人瞻前顾后、患得患失的,虽然是可以理解的、正常的,真的走出那一步,期间的幸苦,尤其是心理上的过渡期,确实是件幸苦的事情。

2、辞职是一个新的开始,需要很强的适应能力和充足的心理准备。其实很多人都会想到新东家的好处,但是真正需要你接受的是新东家的所有一切,就像有 人说过的:爱一个人就爱她的一切,不管是缺点还是优点。所以正确的辞职态度是对新东家的困难有充足的准备,心理上能包容自己不认可的一些东西。不管怎么 说,新的工作环境、新的制度、新的同事,需要你改变去适应。

3、辞职不能是盲目的。辞职固然在很多时候给自己的物质条件上增加了不少,但是这不是唯一的标准。每个人有每个人看重的东西,有的人看重的是舒适的 工作环境,更多的空闲时间等等,有的人看重的是自己未来的发展。我之所以决定要辞职,是因为在老东家找不到我发展的空间了。不管怎么说,辞职的时候需要考 虑的东西很多,但是就我个人的想法来说,我建议大家需要更多的考虑自己的未来的发展。钱这个东西永远是没有够的,在自己有比较好的发展的时候,钱也是水到 渠成的事情。

就个人的发展和职业生涯来说,我觉得有以下几点:

1、做自己喜欢的事情,并持之以恒。自己喜欢的事情,在很多时候,短期内也许不会给你带来很大的经济效益,但是在耐心的沉寂以后,我相信每个人都能厚积而薄发。那时候钱不是问题。

2、学会思考。每个人都会在自己的职业生涯中遇到或多或少、或大或小的困难或者是低迷期,这时候就需要人学会思考,认真的认识自己,定位自己。找出问题的根本原因很重要。学会站在别人的角度思考,学会思考事物的两面性。

3、乐观的心态。上帝不可能将所有好的东西都给你,所以你要学会乐观。乐观的看待问题,乐观的面对困难,乐观的接受上帝给你的一切,好的,不好的。

4、认真。很多时候,简单的事情大家都能完成,注意我这里说的是“完成”,但是要知道如果能将一个简单的事情做到完美,那么就不是所有的人都能做到 的,记住:往往成功的人只是比你更认真,更追求完美。事情做完了以后学会总结,看看能不能有所改进,往前再走一步,也许你就是那个和普通人不同的成功者。

5、养成好的习惯。养成好的工作习惯和生活习惯,一旦一种好的习惯养成以后,你将受用终身。工作上的就不必多说了,生活上的好的习惯,会让你更容易让人接受,让你更好的与人沟通。

6、学会尊重你的同事和上司,甚至是打扫卫生的阿姨。一个人的成功与否,有时候不仅仅是工作上的,工作仅仅是你人生的一部分,你需要很多人帮助你成 功,所以尊重别人很重要。没有同事的Team Work,你不可能独自一人完成一个大型项目;没有上司的支持,你不可能获得必要的成功资源;甚至是打扫卫生的阿姨,如果没有她给你提供整洁干净的工作环 境,你也会受到影响。

7、多倾听别人的意见。耐心的倾听别人的意见,对的也好,错的也好,他们的成功或者失败也许对你来说是一面镜子,也许就是你智慧的火花。

8、勇于创新。墨守陈规的人永远只能走在别人的后面,所以要多尝试,即便是失败了,你也会懂得很多、获得更多的经验。工作中的经验不仅仅需要的是成功的经验,有时候也需要失败的经验来加速你的成长,来支持你做出决断。

9、爱家人。很多时候家人帮你做了原本应该是你完整的事情,他们的支持才能让你后顾无忧的在前台去冲锋陷阵,追求自我的价值。永远不要觉得自己是为家人在工作,所以一些事情家人是天经地义的应该帮你完成的。学会对家人感恩同样重要。

总之,学会工作、学会做人、学会生活是一件非常高深的学问,没有人能代替你,一切都需要你自己去经历,别人给你的意见和建议只是一种参考,你的决定需要你自己来做。你的命运也是一直把握在自己的手中!

有感而发,欢迎讨论。我对软件开发的几点认识

最近在论坛上看到很多热议语言和前途(钱途)的帖子,很多人在热议:我有多少多少年工作经验,我会多少多少门语言,我做过多少多少个项目,等等。我 现在以我的个人观点来说一说: 1、能力是否强和工作多少年无关。同样是工作,但是可能在不同的公司、从事不同的项目、不同的工作流程和工作压力,即使是相同资质的人也会获得不同的知识 和经验。 2、会的语言多并不能代表能力强。人的精力是有限的,一个人不可能同时精通很多东西,多而不精的人只适合做架构师,还需要他或者她有丰富的项目经验和对软 件背后的本质的深刻认识。 3、项目的多少并不能代表实际能力。姑且不论项目的大小区别,且谈自己在项目做所充当的角色才是公司和雇主所关心的,还有就是项目的相关性和连续性也是考 察的一方面,东一榔头西一棒的项目经验其实也是没有太大作用的,个人觉得软件的精细分工的时代已经到来,项目再多、工作经验再长也只能代表你对开发工具有 多么熟悉。 说了这么多的东西,乱七八糟的,呵呵,也许该说说我觉得什么样的人才是好的人才: 1、诚实、有热情,不浮躁。不是仅仅为了糊口而工作,对这个行业有足够的热情和耐心。 2、精通一门语言,熟悉算法,并且能看到语言背后的东西,最好能对语言的本质和硬件的关系有所了解。编程风格良好、认真。 能写让计算机认识的程序的人很多,能写让别人能认识的程序的人很少。 能写正常情况下运行正确的程序的人很多,能写在各种情况下都能运行正确的程序的人很少。 3、某一行业的长时间的工作和项目经验。 4、良好的团队合作能力,沟通和表达能力。 5、足够好的英语能力。

A:不涉及算法的程序???这里所指的算法不是狭义上的树、队列等等,而是广义上的算法,包含前面所说的狭义上的算法,而且还有其他无所不在的思考。 就是一个简单的字符串操作也有不同的做法,好的程序员会思考各种做法的优劣,根据程序的上下文环境选择合适的做法。

B:一定程度上能力和工作多少年是成正比的,这只能在工作的前两年。 如果是一个工作5年和一个工作8年的人相比,就一定是工作了8年的人强吗????

做人比写程序重要 ---- 与兄弟姐妹们共勉

我和他的经历很类似,不过我多了5年的化工,所以比他大了5岁。呵呵。他已经很久不发博文了,我这里替他记录一下。下面是他的原文:

作为一个做了近8年的一个程序员,今天突然顿悟:做人比写程序重要。也许很多人早已明白这个道理,但是也许是因为我后觉后知吧。 我作为一个程序员,始终都有一些孤傲,也许每个程序员都有些孤傲的感觉,这么多年始终有一个错误的想法在我心中:我有技术,技术可以让我找到工作,有工作 就有钱。所以很多时候我考虑问题都很自我,一切都是向钱看。今天突然发现其实除了写程序,我还可以做很多更有意义的事情,这些事情会让家人和朋友获得快 乐,也让自己有不同与编程所获得成就感。例如送孩子上幼儿园,给朋友发一个生日祝福的短消息...... 事无巨细,只要你改变自己的看法,从不同的角度去思考问题,从别人的角度去思考问题,你就会发现其实我可以做的很多,很多比写程序更为有意义更为重要的事 情。

个人工作13年的一些人生真实领悟

此文不定期的更新,想起来就写一些,我都忘了我曾经会过什么了。你可能会在许多的文章里看到类似的,但这些是我个人的真实体会。

1 技术服从于业务

此问题以前的一个文章提过,不再多说。

适用于大多数对技术的盲目崇拜者。在绝大多数公司,觉大多数项目里,技术不是最重要的。而我们绝大多数人都在这些占绝大多数的公司里面。

2 你没有权利选择领导,但可以选择公司

不要抱怨你的领导如何如何,你可以

1 )取代他的位置,你来做领导

2 ) 离开这个公司

3) 老实的干活

3 有了选择真好,有了太多的选择,不一定好

有感于.net框架的易用与Java框架的灵活。客人口味不同而已。我一直用中国移动,但并不代表中国联通就不好。

4 让朋友觉得你很棒,让敌人觉得你很傻。

好酒不怕巷子深的年代已经不存在了。我们要学会总结,学会包装和展示自己。这和中国几千年的传统谦虚美德并不矛盾。

5 认清自己是最难的

人生要有理想,但不能好高骛远。能够真正知道自己能做什么可不是件简单的事情。如同包拯的主簿公孙策,如同黄忠和赵丽蓉。

6 名、利、(情),真实了解你现在正在干什么

除去生存与国家利益这类重大问题外,我们做任何事情应该不会超过这3个,其中名利二字尤其重要。

你去一个公司,要不就为了学到东西,那就不要过分在意收入

如果你去一个公司就是为了钱,那就不要在意做什么工作。

中庸的人会一直在懊恼,愤恨,指责所有的他看着不满意的人和事。

“情”我就不说了,呵呵呵....

7 我为人人,人人为我,请注意顺序

适用于论坛,团队之类的多人合作的情况。你只有先付出,别人才可能付出。这是一个良性循环。 你帮了更多的人,他们总会帮到你的。

先写这些,想到了继续编辑.

一个针对初学者的自学顺序推荐

目标,一个能运行的blog/bbs

  • 搭建Tomcat运行环境
  • 编写hello world 的页面
  • 编写登陆页面 ,输入用户名和密码,用Post方法提交到检查页面
  • 编写登陆检查页面判断用户名是否为admin,密码是否为1234,如果是,显示登陆成功,否则显示失败
  • 记录登陆标志到session
  • 完善首页,判断如果没有登陆,则自动转到登陆页面,如果登陆,显示一段欢迎信息
  • 安装MySQL/SQL Server 数据库,并配置JDBC驱动
  • 数据库建立用户表格,ID,用户名(唯一),密码字段(not null),并插入admin用户,并初始化密码。
  • 登陆页面里直接用JDBC连接数据库,并验证admi的密码
  • 将连接部分移植到Java Bean里面,在页面简单调用
  • 下面就不说这么细节了,你需要向数据库增加用户
  • 编辑和删除用户
  • 考虑多个管理员同时管理的问题,并发问题,可以考虑用乐观锁
  • 将所有数据库操作封装到对应Bean里面
  • 引入Hibernate/JPA/其它持久层, 增加对用户表的配置
  • 增加一个持久化对象,栏目,包括编号和栏目名称,栏目名不能重复
  • 实现栏目的管理
  • 增加发言持久化对象,包括编号,栏目,标题和不大于1000字的内容,使用数据库的时间作为发言时间
  • 增加栏目与发言的1对多关系
  • 实现文章的管理
  • 屏蔽发言里面的特殊字符,包括标题和内容
  • 制作栏目与文章的分类导航和使用,方便的在各栏目间浏览和管理发言
  • 增加发言的用户属性,并增加用户-发言的1-n的映射
  • 修改发言机制,只有登陆的用户才能发言
  • 发言的用户默认为当前登录的用户
  • 增加栏目和用户之间的管理员n-n关系
  • 完善栏目的管理,可以指定任意个管理员
  • 栏目支持多极分类,即可以有下级,下级好可以有下级(难点)
  • 发言的长度增加,使用CLOB存储(难点)
  • 发言允许增加附件。附件需要持久化保存BLOB,全部保存到数据库,包括附件的文件名,类型,长度等,一个发言允许多个附件
  • 发言页面提供附件的下载
  • 修改发言数据结构,允许回复(难点),一个发言允许任意个回复
  • 我们把单独增加的发言叫主题,其它的叫回复
  • 发言的分页显示(小难点)
  • 回复的分页显示
  • 为了减少数据库的占用,将附件本体保存到磁盘上,修改数据结构,让附件依然能够下载
  • 引入富文本编辑器,丰富发言的页面。(难点)
  • 增加主题的精华属性
  • 增加收藏属性,每个用户可以收藏多个主题(引入Ajax)
  • 增加权限和角色
  • 增加不同的操作,比如发帖,回复,附件,收藏,精华
  • 每个用户属于一个角色,不同角色有不同的权限
  • .... 你自己发挥吧

老紫竹的华为面试之旅

由于各种原因,我已经5年没有被别人面试了。

收到通知

2008年5月29日,接到了华为的一个系统设计师的职位面试通知,怀着多接触,交交朋友的心态,我同意过去看看。

到达北京

2008年5月30日,到了北京通州区的姥姥家,顺便看看我的宝贝女儿,朵朵。 他已经在姥姥家1个月了。晚上从网上粗粗看了华为的一点介绍,以及一些群体面试的技巧。

面试路上

2008年5月31日,由于约定早上8:30就要到达面试场所,不知道路途上需要多长时间,清晨5:40就起床了。吃完早点后转轻轨,转地铁,到上 帝站下车,转447公共汽车到达了【上帝大厦】,时间是8:10。来到面试地点,已经有2位在我前面了。签到之后,在一个培训室开始了漫长的等待...

第一个面试

由于这个面试是通知我的那个人,他已经对我有了一定的了解,且为他的同事提供了多应用,多域名情况下的单点登录问题的解决方案。大致聊了一下,填写了【职务申请表】,包括工作经历和期望的薪资等。然后继续回到培训室等待二面。

第二个面试

大家坐到一起,围成半圆形,直边是4位面试的人员。每人发了笔和纸,书写自己的名字。大家先花1分钟做自我介绍,包括个人的情况,爱好,自认的2个 最大的优点和1个缺点等。一个小姑娘第一个发言,我这个老家伙只有第二个发言了。呵呵,没办法,看岁数,他们都比我小几岁才对。

由于我对业务和技术的认识发生个改变,我的性格也有一点点的变化,外向了一点点。个人介绍非常简单

1995年从天津大学毕业,干了5年化工,2000年由于在厂子无法活下去,薪水太低,转行到IT,已经做了8年,其中Java用了6年。 优点是自认是个好人:朋友不多但都是靠得住好朋友,自学能力强:到目前未参加过任何培训班,全部自学,缺点是性格还是内向了一点,不过已经比以前好多了。

我看许多人都事先准备了自己的个人介绍,文字也很有趣,看得出是下了功夫的。

介绍完毕,大家分别对自己印象最深的人做出评价。呵呵,我这个老家伙受到了一些人的关注。原因是,我一直在仔细的听他们介绍(这是对人家最基本的尊重),并记录着什么(我在记他们的姓名,所擅长的东西,以及我感觉的性格情况等)。

正题开始。考官发布面试题目,要求大家分成2组,在各自的地方,规定的时间内将一个多项答案进行重要度排序,然后由组内一位人员进行结果的公布。

宣布完毕,马上询问了几个人员,让他们重复刚才的题目。如果你仔细听了,一定没有任何问题,否则.. 你等着被淘汰吧....

由于年龄和刚才的表现,我做了组长(呵呵,有趣),那个第一个发言的小姑娘主动做了时间的控制(她是个很有头脑的家伙,如果和她合作你会感到很舒服,她心很细,且很有胆量)。

排序的过程还算顺利。大家从里面找出最重要的,一个人提议,其它人一起决定,有歧义时大家用最快的速度讨论,必要时我使用自己的组长权利,拍板决定。最后大家核对了结果,全票通过。然后在规定时间内返回了。

另一组明显慢了一点,超过了规定的时间,被考官质问了。 看来大家还是要注意考官的问题,特别是时间的控制。

考官询问各自排序的原则,并给出最终排序的结果。我们组先返回,所以先回答了结果。然后对方回答。

注意,如果你不是有心人,你一定只注意听,而没有记录,这样你将无法对双方的答案进行区别。我也是对方说出1半以后才反应过来的。幸好考官也没听清楚,让对方重复了一次,我想这是他们故意的。如果有些人还没有注意,我想他们要别淘汰了。

然后双方对2组区别最大的点进行规定时间的讨论,并试图说服对方。如果你没有记录,估计你也没有什么观点了。

考官再次询问了个别人,让他们重复刚才的问题。再次证明,面试时一定要注意力集中,且头脑要清晰。

讨论完毕,大家都是用了超过规定的时间,没有人进行时间控制,大家都忙着阐述各自的观点呢...呵呵。

然后,考官对个别人进行了提问。主要是问你在这次讨论中,你在团队中的作用是什么?

此轮结束,回去等待通知。

午饭

已经中午12点多了,部分人被叫了出去。然后进来人告诉我们领餐票,下午继续面试。

中午遇到了几个前面出去的人,他们没有被通知下午继续,估计第二轮被淘汰了。其中几个都是被单独提问的人员,且回答的不是很理想。估计考官认为他们在团队里没有发挥自己的作用。

第三个面试

上机在规定时间内做XX个选择题,我根据直觉很快完成了,估计是测试性格的。然后继续进行漫长的等待。

第四个面试

2个考官面试我,主要是了解以前的工作情况,特别是离职的原因。还询问了对以后工作的计划,以及对华为还有什么问题需要了解的。他们介绍了华为。

我主要询问了加班和薪资待遇组成问题。

继续漫长的等待。。。

第五个面试

我竟然是最后,我前面的小伙子,是另一个组的组长,也是很棒的一个,我和他交上了朋友。其他人都在我不知道的情况下离开了。大部分是明后天等待面试结果吧。

那个小伙子面试后轮到我,他说在门外等我出来。。。

面试的看来是一个高级人员,主要还是我的工作情况,以及我对以后工作的考虑。特别询问了我提出的薪酬数额的想法。我由于不熟悉数通这个行业,所以我没有要很高的薪水。但我不保证在我熟悉后会再次提出的。他表示同意。

他对薪资进行了更细致的解释。基本就是你做的越久,你的薪水就会增长的越快。当然,是你工作优秀作为前提。

谈得很开心,没有啥问题。大家高兴的结束。

感动

那个小伙子在门口等我。。。。 我们交换了手机号。然后一起走到轻轨站,坐车回家....

面试心得

1 必要的准备,特别是个人的介绍,个人觉得不要太做作了吧
2 注意力集中
3 时间观念
4 明确你在团队里的位置,组织者?参与者?旁观者?结局是不一样的。
5 在可能的情况下,主动表达自己的观点

关于喜爱写代码,不喜欢和客户沟通的问题

zapdos 问

工作后,我才发现我只是喜欢写代码
现在整天没完没了地做什么需求分析,跟客户谈需求,我快要烦死了
我该怎么办啊?各位大佬。

hbofan

LZ,曾经我也以为只写代码,不要做需求分析是最好的
可是慢慢发现,在写代码的过程中总是要改来改去,甚至要重写
因为跟客户需求不符合,没办法.....
就当是为了节省写代码的时间吧,总得有人去谈啊!

java2000_net

比写代码有前途1000倍的工作,你为何不承担起来呢。 我是10年后才认识到这个。
试想:

你拿到了一个项目,你做的很好,但是当拿到用户那里时,你发现用户根本要的不是这个。
于是发生冲突,你被老板骂,然后加班埋头写代码
再次到用户那里,你再次发现用户要的也不是这个。

需求的重要性,要比编码高不只1000倍。错误的方向,做的越好,差距越大。

如果你们有好的分析设计人员,那么你可以专心编码,如果没有呢?? 让那些垃圾笨蛋去指挥你,还不如你自己来。

ydg1024

只会写代码是不行的,做需求分析,写技术文档对一个做软件的来说,也是非常重要的,是必不可少的。
我现在就在改软件,就是因为需求分析没做好,好多地方要改,麻烦死了

nanjg

写代码无非就2个路,一个是做咨询,一个是做管理
你熟悉了行业的需求,马上就会成为这个行业的专家了

有感于Java的学习过程,我该掌握每个细节吗?

细节是魔鬼。

每天都看到许多的新的东西,发现自己还有好多好多的知识要学。越看一个东西,越发现自己不懂的越多。
于是决定用一段时间熟悉它,等自认为已经掌握了之后,又发现许多关联的东西还没有搞懂。至少自己这么认为。

比如一个简单的Statement,
1 他的每个方法你都清楚吗?
2 你都亲自验证过吗?
3 他的每个异常在什么情况下产生?
4 他的源代码你仔细研读过吗?

5 最关键的,和这个类衍生和关联的类和接口,你都熟悉吗?比如Connection 和 ResultSet
6 你知道从JDBC2.0-3.0-4.0的区别吗?每个厂商的实现有啥不同点吗?

Java这东西,内容越来越多,变化越来越快,许多东西不认真的研究过是不会懂得。就算你自己研究过,也有个深度问题。


但是:

如同我们开车,我们每个人真的需要仔细认真的研究汽车的详细构造和原理吗????

如果我们熟悉和了解这些,因为有汽车迷,当然可以最大限度的发挥车的能力。体验到极大的满足感。

不过我个人认为,大部分人只要会开就行了。你只要能把车开到你要去的地方,并保证安全就可以了。

社会是分工合作的,我们不可能擅长每个事情!

对 于学习Java也一样。我们平时接触到的项目,他们完全可以使用我们最常用的技术解决。而根据2-8法则,80%以上的代码不需要优化,至少在我们的绝大 部分项目里是这样(别说这话错,你仔细看看你的代码,他们大部分虽然书写的么有达到你的完美标准,但他能用,而且在这个项目的负荷下面不会有任何问题,我 们不因该把精力放在那些并不重要的代码上)。而运行次数最多,影响使用最大的部分,我们必须使用一段时间专门研究相关的部分就可以了。当然也就加深了对这 部分细节的了解。

大家都有自己最熟悉和擅长的领域,并积累的大量的实用的经验,分工合作才是Java领域最好的方式。



补充:
我 想我需要补充语句:既然是分工合作,当然要每个人对某个自己的领域非常精通,当然要尽可能熟悉它,精通它。我所要表达的意思就是,我们要学会取舍,学会合 作。我们不可能什么都精通。你编程很好,那你美工水平如何?策划能力如何?销售能力如何? 就算同样是Java技术,你擅长B/S,那么C/S如何。 对数据库,你熟悉Oracle,那么DB2如何?

一个道理,大家都清楚,但有时却会不自觉的不这样做。

关于到底用框架,还是纯JAVA的讨论

楼主siu5:
考虑到版权的问题,公司基本上是决定用JAVA的了。但现在又出现了新问题,到底是用框架,还是纯JAVA?
我现在被公司排到一个培训中心学习。JAVA已经学到可以做简单的项目了。
这个学习又学了框架的使用(SSH)。没想到因为使用前要进行麻烦的设置,而且多人合作开发的之后,合并项目的时候,要对XML文件进行复杂的修改(可能还没掌握到巧妙之处),以及经常抛写不知道怎样修改的异常出来,使我对框架的使用不是很感冒。
后来无意之中和该中心的校长的一次谈话中,他对框架的评价更是贬多于褒,更使我对框架提不起兴趣。
但没想到的是,中心教JAVA的老师,对框架却又非常推崇,说可以减少工作量,提高开发效率。

纯JAVA写项目的时候,虽然写Bean、写Form、写Action都比框架麻烦得多,但很多时候,我可以对代码有充分支配权,操作的自由度很大。特别 是有些多表链接T-sql语句,连教JAVA的老师都承认,写起来比用框架灵活得多。而公司的项目,有些方面的业务逻辑比较复杂,我很担心用开了框架之 后,很多东西被封装起来,到时用起来会非常不方便。

所以现在我就很烦恼,到底是在框架上再多下一些功夫,还是用纯JAVA就算了。
还有一个问题,学框架赌场,老师说了一句话,我印象非常深刻的:用了框架,大家以后就可以不用“new”。是不是“new”一些类出来的时候,会占用很多资源?如果接入服务器的用户多了起来,大家都“new”的话,是不是会对服务器做成很大的麻烦?

谢谢!



1楼 ZangXT
框架不会封装你的业务逻辑.
不知道这里的new是什么意思?创建对象的new?
用了框架,大部分类是写在配置文件里,解析的时候通过反射来创建对象.我感觉还不如自己new呢


3楼 dragon0361
在没有足够的功底前建议适当的使用框架,必竞很多框架都是这么多年来大家都认可了的,比方Struts做MVC就很成熟了,关于多人开发最好是使用 VSS\CVS等配置管理工具,对hibernate 掌握如果不熟可以考虑自己写个DB工具类封装JDBC操作,也比较灵活.其实使用什么框架还是需要结合项目的实际情况来考虑的,怎么样好用是相对的.

4楼:jdlsfl
学到底都是一样的
关键不在于你用不用框架
关键是框架是否适合你的项目

5楼 Geomatic
首先,为什么要用框架。看过一句话,我很赞同
框架就是为了实现设计的复用
一个大型的项目,都会有架构师先把系统的整体架构设计好之后,然后程序员
领会他们的思想,再开始编码,这样,不同的程序员写出来的代码可以很好的协同工作。
框架也是如此,现在流行的框架都是很多人一起开发出来,并且不断改进的作品。
充分考虑了整个系统的健壮性,安全性等等。一个团队搞开发的时候,如果大家都会某个
框架,那么可以很容易的明白自己要做什么,怎么做,这是框架的优点之一
其次,框架都是在不断改进,不断完善之中,很多地方,都是大家公认的最佳实践(Best Practise)
对于初学者来说 框架就是一部教科书 可以加快他们的学习进程

然而,由于框架并不总是能符合具体应用的要求,很多地方都是考虑通用的情况,可能会带来一些
效率上,或者其他方面的不足。因此,框架要求使用者对框架有足够深入的了解,必要时候,根据
具体情况改动框架。

总之,对于框架,我是褒多于贬,诚然,很多东西,不同过框架,我们都可以用很灵活的方式
实现,但是,JAVA语言本身就是一门工业化的强类型语言,为大规模的应用而生的,
现在软件也是逐渐向多人构建大型应用发展,所以,我的建议还是用框架。

唉,想到以后大家可能都向编码员方向发展了,惆怅啊


6楼 java2000_net
到目前为止,尚未长时间使用MVC的框架。只是用过taspety 大约1个月。
不好评价框架的详情。


不过,既然这个东西如此流行,我想其道理一定很有说服力。个人认为应该是统一了编码的习惯。
10个人,每人的编码习惯不同,这样大家合作一个项目就会出现很多个版本,这样对于整个项目非常不利。你写的代码和我的连结构都不同,互相看其它9个人的将是非常困难的。虽然结果都出来了,但以后的维护成本将会非常大。
使用框架则正好解决的部分问题,大家都在用同一个东西在做,写出来的也都差不多,都是标签,配置文件和后面的action.详细看具体的某个功能的实现当然就简单的多了,因为那只是局部代码。
如果项目小,2-3个人做,大家约定一下编码规范也是可以的,难道那些MVC出来之前,全世界的人都不编码了吗?呵呵。
配置文件冲突,这个在任何地方都出现,不是框架的问题,而是管理的问题。


8楼:mrshelly
我个人不太喜欢框架. 重要的是系统的整体架构设计了..

设计得好.往往一次 action 不会需要很复杂的业务逻辑去支持.



13楼: For_suzhen
各有利弊,如果出于商业目的,我看裸奔编程还是少数,尤其是对于一些商务应用。
框架是便于开发的。你想自由,可是就看客户乐意不乐意了。需求才有决定权。
记得一高人说过,技术的价值体现在生产力


17楼:RonoTian
我觉得刚开始的时候可以考虑使用纯Java,因为技术框架可以在某些方面节约时间,但是使用第三方的框架其实是需要承担风险的,特别是某些复杂逻辑的实现,使用框架做开发的时间估计比自己写差不多。况且错误难于把握。。。

另每个项目都有自己特定的东西,可以考虑借鉴框架的某些部分的优点,自己写些能够适合项目需求的,有用的框架,反正框架都是人写出来的,自己写为什么不可以??


20楼:yirentianran
1.如果你能很好的完成框架有的功能你可以不使用框架
自己实现类似框架的东西 是很灵活
但是你不用框架你就不用mvc了吗?
那样你的代码可能较难维护
虽然在你类多的时候mvc也可能产生类爆炸
但是相对还是较成熟 封装的东西也较实用

2.你也可以不用spring
但是spring的ioc是一个比较好的思想
你可以自己使用简单工厂模式来实现
spring的aop也很好
你也可以使用发射来自己实现
但是spring的背后有一个开源的团队
我想应该会比很多人自己实现的要成熟

3.hibernate的使用是稍显笨重
但是可以省去很多工作不用自己来做
正确使用也不用太担心效率的问题
理论上会比一般人自己实现持久层要好一些

综上:个人认为框架的使用就是为了方便、快捷、避免重复劳动
没有框架我们一样可以完成工作,但不一定可以同样快捷、很好的完成工作
框架的一些思想都是从实际工作中抽象、分离出来的
如果你可以很好的用自己的代码来实现这些思想、代码很灵活、也很好维护、同时开发也很快捷
你完全没有必要使用框架
不要为了使用而使用


23楼:alloyer
在最初学习的时候,当然是学习纯java,它有助于你理解java底层和内部的一些东西.
不过在实际开始应用时,应当采用框架来完成.
当然,很重要的一点是,你应该有为你的应用选择一个合适框架的能力.这往往是架构师来做的,所以,不是说要使用框架,就可以随便拿一个来用的道理.
框架往往有助于我们整个业务的理解,有助于我们进行代码的重构,减少我们的工作量.

比如,你在开始一个项目前,已经对项目的基本应当采用的架构和技术有了很多了解,并且,你对几种框架有很好的理解.那么,往往,在对这几个框架进行比较, 选择的过程中,你会对你的项目的业务逻辑有更进一下的认识,可以说是做了一种更好的抽象.这往往得益于你选择了正确的框架,它会帮助你对当前的业务逻辑或 者系统的结构豁然开朗.


24楼:gonxi
对于说不用框架好的人,应该是没有明白使用框架的目的。

使用框架不是为了加快开发效率,虽然有些可以提高效率,但通常会增加开发时间。

根本的目的是为了使代码的结构变得规范,有一个标准可以遵循,为了方便以后的维护,这个才是使用框架的长远目标。

如果只是为了实现功能,以后没有别人去维护的话,用java bean ,jsp都可以,就是你用汇编写,也没什么问题。

但如果要别人来维护,你想一下,那个人第一眼看到代码后,他的想法会是什么?

当然你也可以自己做一个规范,但这个规范必须成为你们公司的标准,否则就你一个人遵循是没有意义的。



25楼:gohands
一个人先写好部分配置文件,其他人在上面补充!!
主要还是在于管理
框架只是一个工具一种手段!!
当然开始的时候如果没有太多经验不一定要同时使用SSH!!
根据项目的情况灵活使用!其实就算你使用hibernate,
你也不一定所有的数据库操作都是通过hibernate来实现!


28楼:mengweilil
自己写框架,总不如现成的好吧?毕竟人家是一个team,而且发布了,被到处用了的框架。。。。。。

当然框架不是万能的(记得当年还是一个商业软件框架呢,竟然编译不通过。。。。。C++的,必须自己改了才行。。。。。。)

其实,学习嘛,先IDE,然后框架,等作了一两个项目,回过头来再看基础也没啥不好。


32楼:ZyxIp
系统的灵活性,业务的可扩展性取决于你的设计,而不是取决于你用什么技术.

将整体进行好的业务分类,在选择正确的技术去实现.

最主要的是系统中实现风格统一,相同或类似的功能都进行了统一的封装,各个实现模块有较高的自治程度,可以独立进行修正而不会影响全身.

就算用了hibernate 也只是帮你实现了数据的持久化的功能,但重要的是数据的分类和设计要合理,规整,清晰.

JSP 只是做为生成HTML格式,给用户展示.服务器端的Action类仅是做为从用户处接收数据,然后提交给业务处理对象,根据返回结果流转到不同的页面.

而数据一但到了业务对象这里,和这些框架就没有什么关系了,更喜欢将业务对象都封装成类似的数据容器,将数据提交到存储过程去执行业务规则,这样就算有什么业务变动也可以尽量少的重启服务器.


34楼:wargrey
我就经常自己写框架,不过我还是学生,有时间。反倒是我不怎么推荐使用现成的框架。原因就如ls一哥们所说,习惯了框架离开他就不知道怎么办了。

而且自己些的框架最适合自己所在的群体,不像现成的,那个80/20就不重复了。但是必须为了那一小部分花多余的时间来理解那一大部分,不划算。

所以,想提高自己,或者项目跟别人没有关系,尽量自力更生,没准哪天你的框架将代表中国某领域的突破。



36楼:shicp2008
其实用框架就是 用的一种思路
一种很容易看懂的思路 呵呵
楼主刚学还是用吧
确实很不错
等你用了几年再去想着写自己的框架吧
一开始就对一个东西 特别是很流行的东西抵触 这是大忌


41楼:TinyJimmy 顶4楼
说得挺对!

或可将眼光放高一点, 不要陷在Coding里头. 用框架也好, 纯代码编程也好, 我想你公司的目标都不是代码, 而是为了实现项目或产品的要求.

一个好的公司通常会更关心产品特性:
产品是否能吸引更多客户?
产品是否有效快捷开发?
产品是否易于维护?
产品运行效率是否高?
是否能避免无谓的错误?
...

一切东西都与钱相关! 管理者会在这里找到一个平衡点, 能赚更多钱. 包括送你们去培训框架, 也是为了以后的开发效率, 为了产品出品率.

回到楼主的话题, 对产品而言, 用框架出来的代码和纯Java开发的代码, 真正的区别在于开发出品率/维护成本/运行效率等各方面的平衡. 而对程序员的区别是你熟悉怎么样的代码Coding方式(哪怕XML配置也是Coding的一部分). 一个合适的框架对产品/团队开发会有很大帮助.

举个例子, 使用Struts和直接使用Servlet+JSP处理业务而言, Structs的代码量要大, 还要兼顾MVC的接口. 而Servlet一个类可以处理完. 但是, 对于大型应用而言, 团队会有分工, 业务/页面/美工/数据库管理通常是分离的. MVC恰恰就是这样分离的, 使用Servlet分离灵活性大, 要规范起来不容易(或者说规范的结果就是Struts了).

说了一大堆, 自己都说晕了. 总而言之, 我的想法就两个字: 平衡



43楼: whyf521
1.你如果是公司的项目的实现人员,基本不用考虑使用什么来实现,因为项目的设计架构工程师已经定好了,你照他的要求做就是了;
2.你如果是公司的项目的设计人员,要从项目的大小和客户的需求来设计项目的具体的实现框架;
3.你如果以自己学习为主,那我建议你都看一些,了解现有一些框架,可能以后真正项目中用不上,但这些都是相通的吗!

以上个人意见,只做参考!



45楼:Ant_Yan
我的个人观点:使用框架是提高开发效率的捷径,人家国外的大师把框架做出来,我们还要固执的使用纯Java的话,就永远也赶不上人家
常听见的一个比喻是人家都已经造好汽车到处开了,我们还在关着门造轮子

要真有研究学术的精神,是应该把Java底层学好,把人家框架的设计精髓学到,把思想和素质提高,简而言之就是把我们与他们的差距先想办法缩短再努力赶超

但是要真说到开发项目,使用优秀设计思想的代表框架是项目稳定性能的保证,虽然我们也可以用Java来实现,但代价太大,我们可以去做一些小的模型,但我 不认为任何人有这个时间去真正实现一个大型项目完全不用框架。这是人家几十年前干的事情,我们为什么现在还要去重复这个过程呢?

任何事情都是双面的,我们既不能依赖框架,又要有效的使用框架,衷心希望中国的程序员整理提高,不光是技术上的,更多是思想和素质上的!



46楼:yl0002
能用框架,就用框架。(框架是巨人的肩膀)
框架使用太麻烦(实际原因是自己水平不行)。就不用框架。
最终目标:使用框架、改进框架、扩展框架
要达到最终目标。前提至少是自己实现一遍框架。呵呵。


48楼:zhuyx808
要看项目具体需求来决定,并不是一句话两句话可以说清楚,假如你现在就只有一个页面,你用ssh就是画蛇添足;假如你项目足够庞大,建议还是用框架好点, 毕竟各有分工,MVC不过就是把各个层面划分开来,方便各方面的人去干他专长的东西,美工就专搞页面。。。。各司其职
项目版本管理推荐用svn很好用上手很快,管理也很方便。



61楼:Gump09
好热闹 我也来说说
对于项目首先要有侧重,稳定? 实时? 安全? 等等
这些取舍决定了你是否用框架,用什么框架
我接触过三个项目 框架不一 但都用了(自己开发的或者是既有框架扩展)
框架明显的好处是便于统一编程风格。
成熟框架也可以提供很好的稳定性,安全性,扩展性
对框架稍加扩展即可很好的实现效率的提高。
我不觉得现在还有不用框架的应用。

楼主想问的可能是对现在刚刚起步的人,是学框架好,还是先一步一个脚印的作出自己的一个东西来好。
我的回答可能比较扯。但是我还是要说。其实你自己做一个东西不见得好。
其一,你肯定要花大时间调试,重构,最后很可能做不出来或者直接错误百出
其二,当你埋头调试的时候你是不会想如何让你的东西更好,因为你不知道怎么才能更好
其三,很多东西你想不到,最后会有很多bug
好处就是你从此对编程有了不一样的认识,你上路了
而用框架也有很多不好处
其一,你使用的框架决定了你的学习曲线,你很可能花大时间学习到最后也吃不透
其二,使用框架会让你忽略掉大量编程细节,为以后买下隐患
其三,学则框架不当,会使你的知识结构不能和公司接轨,白白浪费时间
但我还是推荐你使用框架,为什么,因为大家都在用,你就捡公司用什么你就用什么
这样可以让你在进公司不久站在更高的起跑线上。

再说说我接触的项目。
项目无非是调研,基本设计,详细设计,编码,测试,发布,维护。
不知道你在什么样的公司,我这里做基本设计的是比较牛的,同时有一批牛人作选框架,定制框架的工作。
框架有什么好处?
作为基本设计人员,你不用考虑编程,但是如果发布了20个版本以后可能你就有点发怵,新设计在旧程序上
跑的过吗?如果有个好框架,不用担心,20个版本都是一水的整洁,扩展良好哦
详细设计?不要犯难,流程是一样的,什么流程,上个版本的一拷贝你就知道了,省心
编码?按照规范编就行,机能差不多的拷一个改改
测试?还是上一个测试框架,熟阿,快啊
发布?还是上一个发布脚本,乐啊
维护?代码还是一样的流程,找bug 快啊

有人说5个版本以上见功夫,真对
如果你有时间又有自信还有不已物喜不已己悲的心那就自己编
如果只是为了出东西,那用框架
如果只存高远那么选框架,用框架,扩展框架,做框架