当批量处理一些数据的时候,经常会将生成的对象放入集合中,这时候很容易犯一个错误,就是将已经放入集合中的对象修改部分属性后,又重新放入这个集合,表面上看是将一个新的对象放入集合中,实际上原来集合中的对象的属性已经被修改了。因为集合中存放的是对象的引用,改变原来对象的属性,那么从集合中得到的对象属性也就变了。下面一个示例就是这个问题
monitorCompanyRiskGradeTrend = new MonitorCompanyRiskGradeTrend();
monitorCompanyRiskGradeTrend.setId(UUIDUtils.getUUID());
monitorCompanyRiskGradeTrend.setAccountId(accountId);
monitorCompanyRiskGradeTrend.setCompanyName(monitorCompanyRisk.getCompanyName());
monitorCompanyRiskGradeTrend.setRiskGrade(monitorCompanyRisk.getRiskGrade());
monitorCompanyRiskGradeTrend.setCycle("1");
monitorCompanyRiskGradeTrend.setReportDate(calTrend.getTime());
monitorCompanyRiskGradeTrend.setCreateTime(calTrend.getTime());
monitorCompanyRiskGradeTrendList.add(monitorCompanyRiskGradeTrend);
if(1 == calTrend.get(Calendar.DAY_OF_MONTH)){
monitorCompanyRiskGradeTrend.setId(UUIDUtils.getUUID());
monitorCompanyRiskGradeTrend.setCycle("3");
monitorCompanyRiskGradeTrendList.add(monitorCompanyRiskGradeTrend);
if(2 == calTrend.get(Calendar.DAY_OF_WEEK)){
monitorCompanyRiskGradeTrend.setId(UUIDUtils.getUUID());
monitorCompanyRiskGradeTrend.setCycle("2");
monitorCompanyRiskGradeTrendList.add(monitorCompanyRiskGradeTrend);
从表面上看没有逻辑问题,因为数据库中id是主键,那么重新生成主键再存入是没问题的,但是在保存数据的时候就报有重复主键,关键就是因为集合中存储的是对象的引用,重复将同一个对象的引用添加到集合中,保存数据的时候就出现了重复项了。
通过以下代码我们可以清晰的理解这个问题
import java.util.ArrayList;
import java.util.List;
public class Test5 {
public static void main(String args[]){
List<User> userList1 = new ArrayList<User>();
List<User> userList2 = new ArrayList<User>();
User user1 = new User();
userList1.add(user1);
userList2.add(user1);
System.out.println("SET VALUE FOR USERLIST2:");
for(User user: userList2){
user.setName("name");
user.setPassword("password");
System.out.println("PRINT VALUE FOR USERLIST1:");
for(User user: userList1){
System.out.println(user.getName());
System.out.println(user.getPassword());
public static class User{
private String name;
private String password;
public String getName() {
return name;
public void setName(String name) {
this.name = name;
public String getPassword() {
return password;
public void setPassword(String password) {
this.password = password;
示例描述:本章演示如何开始使用JDK进行程序的开发。
HelloWorldApp.java 第一个用Java开发的应用程序。
firstApplet.java 第一个用Java开发的Applet小程序。
firstApplet.htm 用来装载Applet的网页文件
示例描述:本章介绍开发Java的基础语法知识。
accumulationByDoWhile.java 用do~while语句写的累加程序
accumulationByFor.java 用for语句写的累加程序
accumulationByWhile.java 用while语句写的累加程序
boolExample.java 演示boolean变量的程序
charExample.java 演示char变量的程序
compare.java 演示前缀、后缀自加之间区别的程序
constCharExample.java 演示转义字符
converseNumber.java 逆向输出数字
daffodilNumber.java 求水仙花数
division.java 演示整除结果
errorCompoundVariable.java 错误使用局部变量示例
factorial.java 求阶乘
Fibonacci.java 求Fiblnacci数列
GcdAndGcm.java 求最大公约数和最小公倍数
errorInit.java 演示变量初始化错误的程序
integerExample.java 演示各种整型变量的使用
isPrime.java 判断素数
leapYearByIf.java 用if语句判断闰年
leapYearByLogical.java 用逻辑表达式判断闰年
lowToUpper.java 小写字母转换成大写字母
lozengeStar.java 输出一个由*组成的菱形
multiplyTable.java 求乘法口诀表
narrowingConversion_1.java 缩减转换引发错误示例1
narrowingConversion_2.java 缩减转换引发错误示例2
notMultipleOfThree.java 把100-200之间不能被3整除的数输出
outputByDoWhile.java 用while循环随机输出数据
outputByWhile.java 用do~while循环随机输出数据
outputMax.java 求两个数中的最大数
overflowExample.java 演示溢出
precedence.java 演示自加运算符的优先级
primeNumber.java 输出100-200之间的所有素数
ranking.java 评定成绩等级
rankingBySwitch.java 用switch语句评定成绩等级
realExample.java 演示浮点数的有效位数
remainder.java 取余运算示例
showBreak.java 利用标号语句跳转出所有循环嵌套
showCount.java 循环计数示例
showDoubleLoop.java 演示双重循环
showDoubleLoopSe.java 改进的双重循环
showOrder_1.java 演示操作数求值顺序示例1
showOrder_2.java 演示操作数求值顺序示例2
sign.java 用条件运算实现符号函数示例
signByIF.java 用if语句实现符号函数示例
triangleStar.java 输出一个由*组成的直角三角形
upperToLowCase.java 大写转换成小写
variableScopeExample.java 变量使用范围示例
示例描述:本章学习对象和类。
accessMember.java 访问成员变量示例
constructNoPara.java 无参数的构造方法
constructWithPara.java 带参数的构造方法
declareDefault.java 缺省访问权限的使用
declarePrivate.java 私有访问权限的使用
declareProtected.java 保护访问权限的使用
deriveClass.java 子类访问父类变量示例
getLinePara.java 获取命令行参数示例
hasStaticMethod.java 静态成员方法示例
hasStatMember.java 静态成员变量示例
HelloNative.c 用C写的一个小程序
HelloNative.dll 用C生成的DLL文件
HelloNative.exp 用VC编译生成的辅助文件
HelloNative.h 用javah生成的C语言用的头文件
HelloNative.java 准备调用C函数的java文件
HelloNative.lib 用VC编译生成的静态库文件
HelloNative.obj 用VB编译生成的目标文件
HelloNativeTest.java 测试本地化是否成功的类文件
instanceVar.java 定义一个实例成员变量
invokeByObject.java 对象实参传递示例程序
invokeByValue.java 传值调用示例程序
invokeMethod.java 同一个类中调用方法示例
invokeOther.java 类的外部调用方法示例
invokeStaticMethod.java 调用静态方法示例
localVariable.java 演示局部变量
localVSmember.java 局部变量与成员变量同名问题示例
onlyTest.java 对象传值示例
otherClass.java 从类的外部访问对象的成员
showInstVar.java 演示不同的对象拥有不同的成员变量
showMain.java 演示main方法访问本类成员
showMethod.java 演示如何定义一个方法体
showReturn_1.java return语句示例1
showReturn_2.java return语句示例2
showStaicVar.java 演示静态变量的使用
staticBlock.java 演示静态块的使用
staticVar.java 定义静态变量
supplyTest.java 对象作为静态成员使用示例
trySwap.java 试图交换两个形参的值
useOnlyTest.java 创建多个对象,演示this的作用
useStaticBolck.java 使用静态块
useStVar.java 使用静态成员变量
示例描述:本章学习继承与多态。
absClass.java 抽象类定义示例
ancestor.java 基类定义示例1
ancestor_1.java 另一个基类定义
anonymousInner.java 匿名内部类
base.java 定义一个基类
BaseColors.java 一个简单的接口
basePoint.java 一个测试用的基类
Colorable.java 一个子接口
ColoredPoint.java 一个测试用子类
common.java 一个公用类
derive.java 一个测试用子类
differ.java 测试静态方法与实例方法之间的区别
forefather.java 一个简单的基类
grandson.java 上面这个类的子类
hasConstructor.java 拥有构造器的类
hasFinalFun.java 拥有最终方法的类
hasRecall.java 可以完成回调功能的类
HasStatic.java 一个简单的拥有静态成员的类
hideMember_1.java 成员隐藏示例1
hideMember_2.java 成员隐藏示例2
hideMember_3.java 成员隐藏示例3
hideMember_4.java 成员隐藏示例4
hideMember_5.java 成员隐藏示例5
implementABS.java 继承一个抽象类
impRecall.java 实现回调函数
inheritConstruct_1.java 构造器继承示例1
inheritConstruct_2.java 构造器继承示例2
inheritConstruct_3.java 构造器继承示例3
inheritConstruct_4.java 构造器继承示例4
inheritConstruct_5.java 构造器继承示例5
inheritConstruct_6.java 构造器继承示例6
inheritor.java 子类覆盖父类示例
inPack.java 包示例
LotsOfColors.java 定义一个子接口
matching.java 重载解析示例
notInPack.java 用前缀引用包中的类
onlyShow.java 一个简单的接口
Outer_1.java 外部类示例1
Outer_2.java 外部类示例2
Outer_3.java 外部类示例3
Outer_4.java 外部类示例4
Outer_5.java 外部类示例5
Outer_6.java 外部类示例6
Outer_7.java 外部类示例7
Outer_8.java 外部类示例8
overrideMember_1.java 成员方法覆盖示例1
overrideMember_2.java 成员方法覆盖示例2
overrideMember_3.java 成员方法覆盖示例3
overrideMember_4.java 成员方法覆盖示例4
overrideMember_5.java 成员方法覆盖示例5
Paintable.java 实现了多个接口的方法
PaintedPoint.java 实现了多个接口的方法
Point.java 一个简单的类
PrintColors.java 一个子接口
RainbowColors.java 一个子接口
realPoint.java 一个子类
second.java 属于一个命名包的类
showDiff.java 演示隐藏与覆盖之间的区别
showSomething.java 测试运行时多态
stupid.java 试图覆盖最终方法的类,它有错误
Sub.java 一个简单的子类
Super.java 一个基类
testOverload.java 测试方法的重载示例1
testOverload_1.java 测试方法的重载示例2
testOverload_2.java 测试方法的重载示例3
testOverload_3.java 测试方法的重载示例4
useConstructor.java 使用构造器
useHideMember_2.java 试图使用隐藏的成员变量
useInner.java 使用内部类
示例描述:本章学习数组与字符串。
ArrayString.java 字符串数组
assignTwoDime.java 为二维数组赋值
getMaxElem.java 获取数组中的最大元素
incCapicity.java 演示StingBuffer的容量增长
SortDemo.java 排序示例
travelTwoDime.java 遍历二维数组
traversing.java 遍历一维数组
useStrBuf.java 使用StringBuffer示例
useString.java 使用String示例
YanghuiTri.java 构造和显示杨辉三角
示例描述:本章学习Java的异常处理。
demoException_1.java 异常示例1
demoException_2.java 异常示例2
demoException_3.java 异常示例3
demoException_4.java 异常示例4
demoException_5.java 异常示例5
divZeroError.java 除零异常
hasCheckException.java 检查型异常
MyException.java 用户自定义异常
myInput.java 输入数据示例
nestException_1.java 异常嵌套示例1
nestException_2.java 异常嵌套示例2
nestException_3.java 异常嵌套示例3
outBoundError.java 下标越界异常
throwException.java 抛出异常示例
throwsException.java 声明抛出异常
useMyException.java 使用自定义异常
示例描述:本章学习Java的输入和输出。
CopyFile.java 文件复制实例
dir.java 显示目录下的所有文件和目录
encrypt.java 文件加密
FileList.java 自己实现的一个文件名称枚举类
MyDataIO.java 数据输入输出示例
MyFileOutput.java 将键盘读入的文字保存到文件
MyPipedIO.java 管道流示例
MySequenceIn.java 顺序输入流示例
ObjectFileTest.java 序列化对象示例
ReadAndWrite.java 读入和写出数据
ReadAndWriteFile.java 读入数据写出到文件
Student.java 定义一个用来序列化的类
ThreadIn.java 接收数据用的线程类
ThreadOut.java 发送数据用的线程类
TypeFile.java 显示文件内容的类
useScanner.java 用Scanner接收用户的输入
示例描述:本章学习多线程。
enhanceThread.java 一个自己定义的增强型线程类
ThreadImRunnable.java 继承Runnable接口实现多线程
mulThread.java 创建多个线程对象的类
demoJoin.java 演示使用join()以确保主线程最后结束
clicker.java 一个计数用的线程类
demoPri.java 调用上面这个类设置线程优先级示例
myThread.java 自己定义的一个Thread的子类
mutexThread.java 一个能管理临界区的线程类
demoMutex.java 使用上面这个类来演示线程的互斥
commSource.java 一个共享资源的类
demoSynchrony.java 演示线程的同步
setDataThread.java 设置数据的线程类
readDataThread.java 读取数据的线程类
demoEnhanceThread.java 使用自己定义的线程类示例
producer_consumer.java 演示生产者-消费者线程
consumer.java 消费者线程
producer.java 生产者线程
common.java 公有类
示例描述:本章学习运行时类型识别。
Candy.java 一个用来测试的简单类
changeFields.java 改变属性值示例
Circle.java 一个用于测试的简单类
DumpMethods.java 使用反射机制来获取类中的方法
getClassName.java 利用反射机制获取类的名字
invokeConstructor.java 利用反射机制调用构造器
invokeMethod.java 利用反射机制调用成员方法
listConstructors.java 利用反射机制获取构造器列表
listFields.java 利用反射机制获取成员属性列表
listMethods.java 利用反射机制获取成员方法列表
loadClass.java 动态装载一个类
Shape.java 一个用于测试的简单类
useArray1.java 用反射机制使用数组示例1
useArray2.java 用反射机制使用数组示例2
示例描述:本章学习泛型。
demoBounds.java 演示有界类型
demoForceChange.java 演示强制类型转换
demoGeneric.java 泛型类的使用示例
demoGenIF.java 测试泛型类
demoGenMethods.java 泛型方法示例
demoHerit_1.java 泛型类继承示例1
demoHerit_2.java 泛型类继承示例2
demoRTTI_1.java 泛型类的类型识别示例1
demoRTTI_2.java 泛型类的类型识别示例2
demoWildcard.java 通配符使用示例
demoWipe.java 擦拭示例
derivedGen.java 泛型父类继承示例
derivedNonGen.java 非泛型父类继承示例
foo.java 一个有错误的类
Gen.java 无限界的泛型擦拭
Generic.java 一个简单的泛型类
genMethod.java 一个泛型方法
GenStr.java 有限界的泛型擦拭
MinMax.java 泛型接口示例
MyClass.java 实现一个泛型接口
nonGen.java 以非泛型类为父类
simpGen.java 使用泛型类示例
Stats.java 一个有界类泛型
superGen.java 父类是泛型
twoGen.java 有两个参数的泛型类
示例描述:本章学习集合。
CompareScore.java 实现比较器接口
demoAlgorithm.java 集合中简单算法示例
demoArrayList.java 链表使用示例
demoBinSearch.java 二分查找示例
demoEnumSet.java 枚举类型示例
demoHashMap.java 哈希映射示例
demoHashSet.java 哈希集合示例
demoSort.java 排序示例
demoTreeMap.java 树映射示例
demoTreeSet.java 树集合示例
demoVector.java 向量使用示例
job.java 模拟操作系统的进程调度
monkey.java 用链表求猴子选大王
myCompare.java 自己实现的比较器接口
reverseString.java 利用栈将字符串逆序输出
scheduling.java 模拟操作系统的作业调度过程
showClothValue.java 根据用户输入型号输出相应的价格
Size.java 一个枚举类
Student.java 用于记录学生信息的类
示例描述:本章学习类型包装器、自动装箱和元数据。
demoAnno.java 给方法做注释示例
demoAutoBox_1.java 自动装/拆箱机制示例1
demoAutoBox_2.java 自动装/拆箱机制示例2
demoAutoBox_3.java 自动装/拆箱机制示例3
demoInteger.java 整数类型包装器使用示例
demoSingle.java 单成员注释使用示例
DeprecatedClass.java Deprecated注释示例
InProgress.java Documented元注释使用示例
Marker.java 一个被注释的接口
Meta.java 利用反射机制获取方法的注释
MetaAll.java 获取所有注释示例
MyAnno.java 包含了默认值的注释
MyMarker.java 标记注释使用示例
MySingle.java 单成员注释使用示例
OverrideTester.java Override注释示例
SuppressWarningsTester.java SuppressWarnings注释示例
TODO.java Target元注释使用示例
What.java 显示全部注释
示例描述:本章学习常用工具类。
checkEmail.java 利用正则表达式检验Email的合法性
currentTime_1.java 显示时间示例程序1
currentTime_2.java 显示时间示例程序2
currentTime_3.java 显示时间示例程序3
DateAndTime.java 用Calendar显示当前的日期和时间
demoFmtTime.java 使用时间格式转换符输出日期和时间
demoFormatter.java Formatter简单输出示例
demoGroup.java 组匹配使用示例
demoMathing.java 匹配方法使用示例
demoMemory.java 内存管理示例程序
demoPattern_1.java Pattern使用示例1
demoPattern_2.java Pattern使用示例2
demoRandom.java 产生随机数序列示例
demoReplace.java 替换方法使用示例
demoRound.java 取整函数使用示例
elapsed.java 计算程序运行时间
exitJVM.java 从子线程中退出虚拟机
getPI.java 利用随机数求π值
progPI.java 利用反正切函数求π的值
runNotepad.java 启动记事本
showCalendar.java 用GregorianCalendar实现一个万年历
showProperties.java 获取环境属性
textToTime.java 从文本串创建日期对象
useLog.java 利用换底公式求任意对数值
示例描述:本章学习GUI程序设计。
addNodeInJTree.java 在JTree中增加节点示例
AlarmClock.java 小闹钟程序
AWTComponents.htm 为显示AWT组件而编制的网页文件
AWTComponents.java AWT组件示例
AWTFrame.java 用AWT编写的一个简单窗口
CheckAchromatopsiat.java 色盲检测程序
demoBorderLayout.java 边框布局使用示例
demoCardLayout.java 卡片布局使用示例
demoGridBagLayout.java 增强网格布局使用示例
demoGridLayout.java 网格布局使用示例
demoJApplet.htm 运行JApplet的网页文件
demoJApplet.java JApplet使用示例
demoJButton.java 按钮使用示例
demoJCheckbox.java 复选框使用示例
demoJComboBox.java 组合框使用示例
demoJDialog.java 对话框使用示例
demoJFrame.java JFrame简单使用示例
demoJLabel_1.java 图像标签使用示例
demoJLabel_2.java 改变标签上鼠标形状示例
demoJList.java 列表框使用
demoJMenu.java 菜单使用示例
demoJPanel.java 面板使用简单示例
demoJRadioButton.java 单选按钮使用示例
demoJScrollPane_1.java 在JScrollPane创建时添加组件示例
demoJScrollPane_2.java 通过add()方法添加组件示例
demoJSplitPane_1.java 分隔板简单示例1
demoJSplitPane_2.java 分隔板简单示例2
demoJTabbedPane.java 选项板使用示例
demoJTable_1.java 表格使用示例1
demoJTable_2.java 表格使用示例2
demoJTable_3.java 表格使用示例3
demoJTable_4.java 表格使用示例4
demoJTable_5.java 表格使用示例5
demoJText.java 文本框和密码框使用示例
demoJTextArea.java 文本区使用示例
demoJToolBar.java 工具栏使用示例
demoJTree.java 创建JTree示例
ExampleFileFilter.java Sun公司提供的一个文件名过滤器
findDialog.java 查找对话框
fontDialog.java 字体选择对话框
MyTableModel.java 本类实现了一个表格用的模型,取代默认的模型
Notebook.java 记事本
painting_1.java 在面板上画出简单图形示例1
painting_2.java 在面板上画出图形示例2
reMulEvent.java 响应单击按钮事件
showTriDialog.java 用系统预定义的对话框
本章下面还有一些编程要用到的图片和声音文件,不一一列出。
示例描述:本章学习多媒体程序设计。
building.java 调用另外一个houseCanvas类画出一栋房子
CombinerCanvas.java 编写自己的画布,所要显示的图片在此画布上显示
CombinPic.java 合成两幅图片
DrawArcs.java 画椭圆和圆弧示例
DrawLines.java 画直线示例
DrawPoly.java 画多边形示例
DrawRects.java 画矩形示例
fadeInOut.java 淡入淡出效果示例
FillArea.java 填充图形示例
FontsCanvas.java 自行管理字体的画布
GetFonts.java 获取系统中安装的字体示例
GrayFilter.java 自己实现的GrayFilter类
GrayModel.java 实现一个具备灰度变换功能的Model
houseCanvas.java 用直线画出一栋房子
illumination.java 光照特效示例
LightingLiteral.java 字体特效显示示例
ManageFonts.java 自行管理字体示例
mixing.java 显示色彩混合效果
playAudio.java 在Application中播放声音文件
playMP3.java 增强的声音播放文件
playMusic.htm 可以播放背景音乐的一个网页
playMusic.java 利用AudioClip播放声音文件
playVideo.java 媒体播放器编写示例
ResizeOval.java 缩放图形示例
ShowFonts.java 建和使用字体示例
SoundBase.java 将Java Sound API封装在一个线程中
TransparencyExample.java 为实现色彩混合效果而定义的画布
viewPic.java 用标签显示图像示例
本章下面还有一些编程要用到的图片和声音文件,不一一列出
示例描述:本章学习数据库程序设计。
AddressList.java 学生信息管理系统实例
deleteData.java 从数据库中删除记录
FirstExample.mdb 本章用到的数据库文件
insertData.java 向数据库中添加新数据
queryData.java 查询数据示例
updateData.java 修改数据示例
示例描述:本章学习C/S网络程序设计。
chatClient.java 聊天客户端程序
chatServer.java 聊天服务端程序
Client.java 一个简单的客户端程序
DownFile.java 文件下载示例
GetHostName.java 根据IP查找主机名
GetIP.java 根据域名查找IP地址
GetMyIP.java 获取本机IP地址
MultiServer.java 可以响应多个客户端的服务程序
myBrowser.java 一个简单的浏览器
Server.java 一个简单的服务端程序
ServerThread.java 一个服务端的线程类
UDPChat.java 用UDP实现的聊天程序示例
示例描述:本章学习JSP程序设计。本章所有文件均已经按照Tomcat网站部署的要求放置在各自的目录下,然后打包成ZIP文件。读者只需要解包后放置在某一分区中,然后在Tomcat中配置好入口就可以使用。
下面的文件均放置在ROOT目录下面
ArbitraryObject.java 实现一个事件监听者接口的类
calendar.jsp 用JSP实现的日历
count.txt 站点计数器保存的数据文件
counter.jsp 用JSP实现的计数器
faq.java 连接数据库用的JavaBean
leaveword.htm 留言板的主页面
Model.java 自己定义的事件源类
ModelChangedListener.java 自己定义的一个事件监听者接口
MouseMovedExampleEvent.java 事件状态对象示例
MouseMovedExampleListener.java 鼠标事件监听者接口与事件监听者示例
OurButtonCustomizer.java 实现一个“按钮”Beans的定制器
query.jsp 数据库查询程序
saveword.java 用于保存记录的JavaBean
saveword.jsp 后台保存数据的JSP文件
viewword.jsp 查看留言的JSP页面
WeekDayBeanInfo.java 实现BeanInfo接口示例
WeekDayEditor.java 实现属性编辑器接口
下面的文件均存放在chat目录下,是聊天室的组成文件。
chatreg.java 用户注册用到的JavaBean文件
chatreg.jsp 用户注册的前台JSP文件
chatregcof.jsp 用户注册检查JSP文件
chatroom.jsp 聊天室的主页面
confirm.jsp 检查登录是否正确的JSP文件
in.jsp 即将进入聊天室前的提示页面
listuser.jsp 显示聊天室内的所有用户名的JSP文件
logout.jsp 清除用户的相关信息
netchat.jsp 用户进入聊天室的界面文件
showmsg.jsp 显示各个用户所说的话
talk.jsp 用户聊天用的JSP文件
示例描述:本章是一个IM软件的完整代码。
ChatFrame.java 聊天用的主界面程序
ClientManageFrame.java 是好友管理窗口,也是客户端程序的主窗口
DBConnection.java 连接数据库用的JavaBean
FindUserDlg.java 查找好友对话框
FindUserInfo.java 显示用户基本信息
FriendLabel.java 在list列表中显示用户的头像和字符信息
Login.java 用户登录界面
LoginUser.java 定时器的任务类,用于定时获取上线的用户的信息
MyInfo_AboutBox.java 显示作者信息
ReceiveOthersDialog.java 当用户收到陌生人的消息时,这个类向用户提示
RegisterDialog.java 用户注册面板
Server.java 提供各种服务的类
ServerFrame.java 服务器端的主界面
ServerThread.java 与客户端通讯的线程
SetCenter.java 将窗口设置在屏幕中央的类
showTimeTask.java 刷新时间的类
StartServer.java 启动服务器的主类
UpdateDialog.java 更新用户信息的对话框
UserInfo.java 获取用户信息的类
UserInfoBean.java 保存用户信息的一个JavaBean
int和Integer有什么区别?
答:int是java的原始数据类型,Integer是java为int提供的封装类,java为每个原始数据类型都提供了封装类。
String和StringBuffer的区别?
答:String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变的字符序列,所以如果要经常改变某个字符串的话建议使用StringBuffer。
list、set、map问题?
答:set 不允许重复,无序
list 允许重复,有序
map 成对的数据结构,键值必须具有唯一性
Servlet和CGI的区别?
答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上低于Servlet。
面向对象的特征?
答:1:封装:通过定义类并且给类的属性和方法加上访问控制
2:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。
3:多台:不同对象对统一消息作出不同响应称之为多态
4:抽象:忽略与当前主题无关的那些方面,将注意力集中在与当前目标有关的方面
运行时异常和一般异常有何异同?
答:运行时异常时(JVM)java虚拟机在运行过程中发生的问题,比如:内存溢出等问题。这类异常没法要求程序员去一一捕获并抛出,一般异常是Java类库或程序员自己写的代码发生的错误,这类异常可以由我们去一一捕获并抛出。
多线程几种实现方法,同步?
答:多线程有两种实现方法,一种是继承Thread类或者实现Runnable接口。同步就是在方法返回类型后面加上synchronized。
c#中的委托,事件是不是委托?
答:委托就是将方法作为一个参数带入另一个方法叫做委托,事件是一种特殊的委托。
应用程序域?
答:应用程序域可以理解为一种轻量级的进程,起到安全的作用,占用资源小。
Class.forName作用?
答:调用该访问返回一个以字符串指定类名的类对象。
答:JDO是java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。
CORBA?
答:CORBA标准是公共对象请求代理结构,用途为:用不同的程序设计语言书写,在不同的进程中运行,为不同的操作系统开发。
xml解析技术?
答:常用的DOM、SAX等
DOM:处理大型文件时性能下降的非常厉害,适合对xml的随机访问
SAX:事件驱动型的xml解析方法,适合对xml的顺序访问
jsp常用动作?
答:jsp:include 引入一个文件
jsp:useBean 实例化JavaBean
jsp:setProperty 设置JavaBean属性
jsp:getProperty 输出JavaBean属性
jsp:forward 转发
CTS、CLS、CLR分别作何解释?
答:CTS 通用类型系统、CLS 通用语言规范、CLR 公共语言运行时。
Struts1和Struts2原理和区别?
答:Struts1和Struts2是两个完全不同的框架,Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。
Hibernate工作原理,Hibernate数据持久化?
答:Hibernate工作原理:
1:读取并解析映射信息,创建SessionFactory
2:打开Session
3:创建事物
4:持久化操作
5:提交事务
6:关闭Session
7:关闭SessionFactory
Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。
Spring由那几个模块组成?
答:Spring主要由7个模块组成:
1:Spring核心容器:提供了Spring框架的基本功能
2:Spring AOP:通过配置管理特性
3:Spring ORM:Spring框架集成了若干ORM框架
4:Spring DAO:打开关闭数据库连接
5:Spring WEB:为基于WEB服务的应用程序提供上下文服务
6:Spring Context:向Spring框架提供上下文信息
7:Spring MVC:分离模型、视图、控制器、以便更容易定制
折构函数和虚函数?
答:折构函数式销毁一个类的函数,虚函数是为了C++的动态绑定而设计的。
描述你的编程风格?
答:类名首字母大写,常量一般全部大写,给自己的代码加注释。
控制流程?
答:控制流程一般使用if判断条件。有第二分支,多分支,循环结构。循环本质上也是通过判断来实现的。
多形与继承?
答:多形:一个类中多个同名方法。继承:子类继承父类。
jsp内置对象?
答:request 用户端请求
response 回应
pageContext 网页属性
session 会话
out 输出
page 当前网页
exception 错误网页
application servlet正在执行的内容
config servlet构架部件
Struts模型驱动?
答:封装请求参数。
简述JDBC?
答:JDBC数据库连接,是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问。
什么情况下不建议使用Hibernate?
答:当数据量大,并且表关系复杂的时候不建议使用。
sleep()和wait()有什么区别?
答:sleep()是线程类的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但监控状态依然保持,到时候会自动恢复。
wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。
同步和异步,在什么情况下分别使用?
答:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步。在很多情况下采用异步往往更有效率。
数据库三大范式?
答:1:确保每列都是不可分割的原子值
2:确保每列都和主键相关
3:确保每列都和主键直接相关,而不是间接相关
单例模式有哪些好处?
答:单例模式是一种比较常见的设计模式,带给我们以下好处:
1:控制资源的使用
2:控制实例的产生数量
3:让多个不相关的两个线程或进程之间实现通信
为什么要用spring?
答:1、主要将各个框架有效的联系起来,缩短实际编程时间。
2、可以将各个框架进行有效的管理和控制,让数据传输安全。
spring的IOC和DI?
答:控制反转和依赖注入是spring的两大基础作用。主要是将所有组件在spring提供的外部容器中加载。提高安全性,减低耦合性,使各个框架或者类之间的依赖性降低。
什么是声明式的事务管理?为什么要用?spring如何实现声明式的事务管理?
答:声明式的事务管理主要是将在进行对数据库中数据的添加或者修改时需要执行事务管理,主要是为了避免在执行添加或修改的时候添加或修改不完全正确,导致数据丢失。spring使用AOP面向切面的思想进行事务管理的。
spring和Hibernate继承后,定义事务管理特性的时候查询为什么要定义为read-only?
答:因为添加、删除和更新都涉及到了数据库的修改,而查询并未涉及到数据库修改,所以只需要定义只读,这样可以提高效率,进行更加方便的事务管理。
请你谈谈对Hibernate OR映射的理解?
答:将数据库中的每一张表都映射成一个实体。
配置了lazy="true"一定会懒加载吗?
答:不一定,如果在配置中你也使用了fetch属性的话此时lazy就会失效。
Hibernate数据库标识与主键之间的认识?
答:标识是为了方便和简介映射文件,主键是为了让数据不会重复。
为什么每次请求都要创建一个Action对象?
答:Struts2每次请求的时候都会创建一个action实例,这样会保证线程的安全。Struts1只是在第一次请求的时候创建一个action实例,以后每次相同的请求都直接从内存中去读取,它是单例模式,安全性较差。
Struts2是如何实现MVC模式的?
答:在Struts2里面是将每次页面的请求进行处理,然后将请求需要输出的数据转发到需要做数据显示的页面。Struts2只是起到一个数据接收和转接的功能,就是Controller控制器,而传来数据的页面叫view显示层,Struts2将数据提交给进行处理的类叫Model模型层,专门进行数据处理和数据库的连接。
heap和stack有什么区别?
答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进先出的方式进行处理。堆是栈的一个组成元素。
EJB和JavaBean的区别?
答:EJB不是一般的JavaBean,EJB是企业级的JavaBean,EJB一共分为3种,实体Bean,消息Bean,会话Bean。书写EJB要遵循一定的规范,另外要运行EJB,你需要有相应的EJB容器,比如WebLogic、jboss等,而JavaBean不需要,只需要安装Tomcat就可以了。EJB用于服务端的应用开发,而JavaBean用于客户端应用开发。
答:触发器是一种特殊的存储过程,主要通过事件来触发而被执行。
什么是存储过程?用什么调用?
答:存储过程是一个预编译的SQL语句,优点是允许模块化的设计。就是说只需要创建一次,以后再程序中就可以调用多次。使用存储过程比单纯的SQL语句要快,可以用一个命令对象来调用存储过程。
索引优缺点?
答:索引可以提高对数据库中数据的检索,缺点是减慢了数据录入速度,同时也增加了数据库的尺寸大小。
什么是事务?什么是事锁?
答:事务就是被绑定在一起,作为一个逻辑单元执行的SQL语句。如果任何一个操作失败,那么整个就失败。共同失败或共同成功。锁可以保证事务的完整性和并发性。
什么是视图?游标是什么?
答:视图是一种虚拟的表,具有和物理表相同的功能。游标是对查询出来的结果集作为一个单元来有效的处理,可以对结果集的当前行做修改。
select执行顺序?
答:from
where
group by
having
select
order by
Collection和Collections的区别?
答:Collection是集合类的父类,继承它的主要由set和list
Collections是针对集合类的帮助类,它提供了一系列针对集合的搜索,排序,线程安全化等操作。
final、finally、finalize的区别?
答:final用于声明属性方法和类,分别表示:属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句的一部分,表示总是执行。
finalize是Object的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
assert是什么?什么时候用到?
答:断言,可以将断言看成是异常处理的一种高级形式,可以用来判断某个特定的表达式或值是否为真。
接口是否可以继承接口?抽象类是否可以实现接口?抽象类是否可以继承实体类?
答:接口可以继承接口,抽象类可以实现接口,抽象类可以继承实体类。
引用传递和值传递?
答:引用传递:形参改变影响实参
值传递:形参改变不影响实参
当一个线程进入一个对象的synchronized方法后,其他线程是否可进入此对象的其他方法?
答:其他方法前是否加了synchronized关键字,如果没加则能。
说出servlet生命周期?
答:servlet实例化时调用init方法,得到请求时调用service方法,service方法自动派遣doget或dopost方法,最后当实例销毁时调用destroy方法。
error和exception有什么区别?
答:error是指错误,通常程序员不能通过代码来解决。底层环境或硬件问题。
exception是指异常,可以通过代码来解决的问题。
forward和redirect的区别?
答:forward是转发,浏览器跳转后不显示新的地址。
redirect是重定向,浏览器跳转后显示新的地址。
对比之下forward更加高效,并且它有助于隐藏实际地址,但是有些情况则必须使用redirect,否则会报异常。
jsp中动态include和静态include的区别?
答:动态include用jsp:include实现,适用于动态页面,可以携带参数
静态include用include伪码实现,适用于静态页面
math.round(11.5)等于多少?math.round(-11.5)等于多少?
答:Math.round()对数字进行四舍五入
Math.round(11.5)=12
Math.round(-11.5)=11
String s=new String("xyz");创建了几个String Object?
答:创建了两个String对象,一个保存的引用地址,一个保存实际的值。
数组有没有length()这个方法?String呢?
答:数组里面没有length()方法,而是length属性。String有length()这个方法。
swtich()能否作用在byte、long、String上?
答:swtich()传递的应该是一个整数表达式,所以它的值只能是:int、short、char、byte所以long和String都不能作用在swtich()上。
jsp和servlet之间的联系?
答:jsp前段动态页面,servlet是纯java类
jsp被编译之后会转换为servlet执行
java基本数据类型有哪些?String是不是基本数据类型,他们有何区别?
答:基本数据类型8种:int、short、byte、long、float、double、char、boolean
String不是基本数据类型,引用数据类型。
区别:基本数据类型比较实用“==”,引用数据类型实用equest,并且引用数据类型存放的是地址而不是具体的值。
写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc?
答:String s="bbbwlirbbb";
s.replaceAll("wlirbbb","hhtccc");
如何将数值型字符转换为数字(Integer,Double)?
答:可以用Integer.parseInt()和Double.parseDouble()方法
如何将数字转换为字符?
答:可以使用String的valueOf()方法。
如何取得1970到现在的毫秒数?
答:可以用getTime()方法。
如何格式化日期?
答:可以用SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
判断是否有子文件?判断是否有子目录?判断文件是否存在?
答:判断是否有子文件使用file.isFile()
判断是否有子目录使用file.isDirectory()
判断文件是否存在使用file.exists()
继承、重载、覆盖问题?
答:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。
重载:在一个类中方法名和返回类型相同,参数不同。
覆盖:在子类中覆盖父类的某个方法,要求方法名相同,参数类型相同。
Statement和PreparedStatement之间的区别?
答:Statement比PreparedStatement速度慢
PreparedStatement是预编译,插入时速度高于Statement
Statement创建速度很慢,常用选择PreparedStatement
Session机制?
答:session机制是一种服务器端机制,服务器使用一种类似于散列表的结构来保存信息。
jsp和servlet中的请求转发分别如何实现?
答:jsp可以使用jsp:forward标签转发
servlet可以使用request.getRequestDispatcher()实现转发
介绍j2ee、j2se、j2me的区别?
答:j2ee(企业版):主要用于企业web开发
j2se(标准版):主要用于web开发,但缺少企业版的一些特性
j2me(微小版):主要用于手机开发
J2ee提供的技术?
答:j2ee提供的技术有EJB、servlet、jsp等。
什么是Application Server?
答:Application Server 应用服务器
简单介绍连接池的优点和原理?
答:数据库连接和关闭是比较花费时间的一件事,而连接池可以提高我们的工作效率。
刚开始创建一定数量的池连接,当需要时从池连接中拿出一个,用完之后再把这个连接重新放回连接池。
Web.xml的作用?
答:Web.xml会在程序启动时执行,如果想在程序刚启动的时候执行一些方法的话可以配置在Web.xml中。
简单介绍您所了解的MVC?
答:在项目中使用MVC模式会使项目分工更加明确,结构更加清晰
M model 模型层:JavaBean
V view 视图层:jsp html
C controller 控制层:servlet
简单介绍你所了解的XML?
答:XML可扩展标记语言,可以用来标记数据,定义数据结构,是一种允许用户自定义标记的语言
简单介绍您所了解的structs、spring和hibernate?
答:struts:控制层Action,页面标签和Model数据,调用业务层
Spring:Aop管理事务控制,IOC管理各个组件的耦合
Hibernate:负责数据库和对象的映射,负责Dao层
因为你去公司面试,公司让你写笔试,不可能说XX一个题目写两页纸写的太详细,所以以上答案有的可能比较简短,没有说出重点,请大家补充,如果大家有什么更好的答案请拿出来一起分享
前言:本资源来自于javaeye,原资源链接地址:http://www.javaeye.com/topic/67398
原文如下:
以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。
如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 .
类中用到了 jakarta-oro-2.0.jar 包,请大家自己在 apache网站下下载
在这是junit测试单元类我就不提交了,在main()方法中有几个小测试,有兴趣自己玩吧.
这个工具类目前主要有25种正规表达式(有些不常用,但那时才仔细深入的研究了一下正规,写上瘾了,就当时能想到的都写了):
1.匹配图象; 2 匹配email地址; 3 匹配匹配并提取url ; 4 匹配并提取http ;
5.匹配日期 6 匹配电话; 7 匹配身份证 8 匹配邮编代码
9. 不包括特殊字符的匹配 (字符串中不包括符号 数学次方号^ 单引号' 双引号" 分号; 逗号, 帽号: 数学减号- 右尖括号> 左尖括号 0)
12 匹配正整数 13 匹配非正整数(负整数 + 0)
14 匹配负整数; 15. 匹配整数 ;
16 匹配非负浮点数(正浮点数 + 0) 17. 匹配正浮点数
18 匹配非正浮点数(负浮点数 + 0) 19 匹配负浮点数;
20 .匹配浮点数; 21. 匹配由26个英文字母组成的字符串;
22. 匹配由26个英文字母的大写组成的字符串 23 匹配由26个英文字母的小写组成的字符串
24 匹配由数字和26个英文字母组成的字符串; 25 匹配由数字、26个英文字母或者下划线组成的字符串;
java源码:
* Created on 2005-4-15
* Summary of regular-expression constructs 正则表达式结构简介:
* Construct Matches
* Characters 字符:
* x The character x x 字符 x
* \\ The backslash character \\ 反斜杠
* \0n The character with octal value 0n (0 <= n <= 7) \0n 十进制数 (0 <= n <= 7)
* \0nn The character with octal value 0nn (0 <= n <= 7) \0nn 十进制数 0nn (0 <= n <= 7)
* \0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7) \0mnn 十进制数 0mnn (0 <= m <= 3, 0 <= n <= 7)
* \xhh The character with hexadecimal value 0xhh \xhh 十六进制数 0x
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
Subject:抽象被观察者,把所有观察者对象的引用保存到集合中,然后
提供添加,移除,和通知观察者对象更新的方法。
ConcreteSubject:被观察者,集合存放观察者,重写增删和通知观察者
的方法,当发生变化时通知观察者更新。
Observer:抽象观察者,定义一个更新接口,给被观察者更新的时候调
ConcreteObserver:具体观察者,继承抽象观察者,实现具体的更新方法
假设有三个人,拍卖师,拍卖者1,
我现在在英国一家软件公司任技术带头人。我是计算机科学的硕士。我主要使用 .NET 1.1/2.0, C#, VB.NET, ASP.NET, VC++ 6, MFC, ATL, COM/DCOM, SQL Server 2000/2005等。最近我在学习 .NET 3.x 的全部内容。我的免费源代码和文章网站是 http://aishai.netfirms.com
职业:团队带头人
位置:英国
C# 是一种具有 C++ 特性,Java 样式及 BASIC 快速建模特性的编程语言。如果你已经知晓 C++ 语言,本文将在不到一小时的时间内带你快速浏览 C# 的语法。如果熟悉 Java 语言,Java 的编程结构、打包和垃圾回收的概念肯定对你快速学习 C# 大有帮助。所以我在讨论 C# 语言构造的时候会假设你知道 C++。
本文通过一系列例程以简短但全面的方式讨论了 C# 语言构造和特性,所以你仅需略览代码片刻,即可了解其概念。
注意:本文不是为 C# 宗师而写。有很多初学者的 C# 文章,这只是其中之一。
接下来关于 C# 的讨论主题:
? 编程结构
? 命名空间
? 数据类型
? 变量
? 运算符与表达式
? 枚举
? 语句
? 类与结构
? 修饰符
? 属性
? 接口
? 函数参数
? 数组
? 索引器
? 装箱与拆箱
? 委托
? 继承与多态
以下主题不会进行讨论:
? C++ 与 C# 的共同点
? 诸如垃圾回收、线程、文件处理等概念
? 数据类型转换
? 异常处理
? .NET 库
和 C++ 一样,C# 是大小写敏感的。半角分号(;)是语句分隔符。和 C++ 有所区别的是,C# 中没有单独的声明(头)和实现(CPP)文件。所有代码(类声明和实现)都放在扩展名为 cs 的单一文件中。
看看 C# 中的 Hello World 程序。
复制内容到剪贴板
using System;
namespace MyNameSpace
class HelloWorld
static void Main(string[] args)
Console.WriteLine ("Hello World");
C# 中所有内容都打包在类中,而所有的类又打包在命名空间中(正如文件存与文件夹中)。和 C++ 一样,有一个主函数作为你程序的入口点。C++ 的主函数名为 main,而 C# 中是大写 M 打头的 Main。
类块或结构定义之后没有必要再加一个半角分号。C++ 中是这样,但 C# 不要求。
每个类都打包于一个命名空间。命名空间的概念和 C++ 完全一样,但我们在 C# 中比在 C++ 中更加频繁的使用命名空间。你可以用点(.)定界符访问命名空间中的类。上面的 Hello World 程序中,MyNameSpace 是其命名空间。
现在思考当你要从其他命名空间的类中访问 HelloWorld 类。
复制内容到剪贴板
using System;
namespace AnotherNameSpace
class AnotherClass
public void Func()
Console.WriteLine ("Hello World");
现在在你的 HelloWorld 类中你可以这样访问:
复制内容到剪贴板
using System;
using AnotherNameSpace; // 你可以增加这条语句
namespace MyNameSpace
class HelloWorld
static void Main(string[] args)
AnotherClass obj = new AnotherClass();
obj.Func();
在 .NET 库中,System 是包含其他命名空间的顶层命名空间。默认情况下存在一个全局命名空间,所以在命名空间外定义的类直接进到此全局命名空间中,因而你可以不用定界符访问此类。
你同样可以定义嵌套命名空间。
Using
#include 指示符被后跟命名空间名的 using 关键字代替了。正如上面的 using System。System 是最基层的命名空间,所有其他命名空间和类都包含于其中。System 命名空间中所有对象的基类是 Object。
除了以下差异,C# 中的变量几乎和 C++ 中一样:
1. C# 中(不同于 C++)的变量,总是需要你在访问它们前先进行初始化,否则你将遇到编译时错误。故而,不可能访问未初始化的变量。
2. 你不能在 C# 中访问一个“挂起”指针。
3. 超出数组边界的表达式索引值同样不可访问。
4. C# 中没有全局变量或全局函数,取而代之的是通过静态函数和静态变量完成的。
所有 C# 的类型都是从 object 类继承的。有两种数据类型:
1. 基本/内建类型
2. 用户定义类型
以下是 C# 内建类型的列表:
类型 字节 描述
byte 1 unsigned byte
sbyte 1 signed byte
short 2 signed short
ushort 2 unsigned short
int 4 signed integer
uint 4 unsigned integer
long 8 signed long
ulong 8 unsigned long
float 4 floating point number
double 8 double precision number
decimal 8 fixed precision number
string - Unicode string
char - Unicode char
bool true, false boolean
注意:C# 的类型范围和 C++ 不同。例如:long 在 C++ 中是 4 字节而在 C# 中是 8 字节。bool 和 string 类型均和 C++ 不同。bool 仅接受真、假而非任意整数。
用户定义类型文件包含:
1. 类 (class)
2. 结构(struct)
3. 接口(interface)
以下类型继承时均分配内存:
1. 值类型
2. 参考类型
值类型是在堆栈中分配的数据类型。它们包括了:
? 除字符串,所有基本和内建类型
? 结构
? 枚举类型
引用类型
引用类型在堆(heap)中分配内存且当其不再使用时,将自动进行垃圾清理。和 C++ 要求用户显示创建 delete 运算符不一样,它们使用新运算符创建,且没有 delete 运算符。在 C# 中它们自动由垃圾回收系统回收。
引用类型包括:
? 类
? 接口
? 集合类型如数组
? 字符串
C# 中的枚举和 C++ 完全一样。通过关键字 enum 定义。
复制内容到剪贴板
enum Weekdays
Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
除了内存分配的不同外,类和结构就和 C++ 中的情况一样。类的对象在堆中分配,并使用 new 关键字创建。而结构是在栈(stack)中进行分配。C# 中的结构属于轻量级快速数据类型。当需要大型数据类型时,你应该创建类。
复制内容到剪贴板
struct Date
int day;
int month;
int year;
class Date
int day;
int month;
int year;
string weekday;
string monthName;
public int GetDay()
return day;
public int GetMonth()
return month;
public int GetYear()
return year;
public void SetDay(int Day)
day = Day ;
public void SetMonth(int Month)
month = Month;
public void SetYear(int Year)
year = Year;
public bool IsLeapYear()
return (year/4 == 0);
public void SetDate (int day, int month, int year)
如果你熟悉 C++ 面向对象的方法,你一定对属性有自己的认识。对 C++ 来说,前面例子中 Date 类的属性就是 day、month 和 year,而你添加了 Get 和 Set 方法。C# 提供了一种更加便捷、简单而又直接的属性访问方式。
所以上面的类应该写成这样:
复制内容到剪贴板
using System;
class Date
public int Day{
get {
return day;
set {
day = value;
int day;
public int Month{
get {
return month;
set {
month = value;
int month;
public int Year{
get {
return year;
set {
year = value;
int year;
public bool IsLeapYear(int year)
return year%4== 0 ? true: false;
public void SetDate (int day, int month, int year)
this.day = day;
this.month = month;
this.year = year;
这里是你 get 和 set 属性的方法:
复制内容到剪贴板
class User
public static void Main()
Date date = new Date();
date.Day = 27;
date.Month = 6;
date.Year = 2003;
Console.WriteLine
("Date: {0}/{1}/{2}", date.Day, date.Month, date.Year);
你必须知道 C++ 中常用的 public、private 和 protected 修饰符。我将在这里讨论一些 C# 引入的新的修饰符。
readonly
readonly 修饰符仅用于修饰类的数据成员。正如其名字说的,一旦它们已经进行了写操作、直接初始化或在构造函数中对其进行了赋值,readonly 数据成员就只能对其进行读取。readonly 和 const 数据成员不同之处在于 const 要求你在声明时进行直接初始化。看下面的例程:
复制内容到剪贴板
class MyClass
const int constInt = 100; //直接进行
readonly int myInt = 5; //直接进行
readonly int myInt2;
public MyClass()
myInt2 = 8; //间接进行
public Func()
myInt = 7; //非法
Console.WriteLine(myInt2.ToString());
sealed
带有 sealed 修饰符的类不允许你从它继承任何类。所以如果你不想一个类被继承,你可以对该类使用 sealed 关键字。
复制内容到剪贴板
sealed class CanNotbeTheParent
int a = 5;
unsafe
你可以使用 unsafe 修饰符在 C# 中定义一个不安全上下文。在不安全上下文中,你可以插入不安全代码,如 C++ 的指针等。参见以下代码:
复制内容到剪贴板
public unsafe MyFunction( int * pInt, double* pDouble)
int* pAnotherInt = new int;
*pAnotherInt = 10;
pInt = pAnotherInt;
*pDouble = 8.9;
如果你有 COM 的思想,你马上就知道我在说什么了。接口是只包含函数签名而在子类中实现的抽象基类。在 C# 中,你可以用 interface 关键字声明这样的接口类。.NET 就是基于这样的接口的。C# 中你不能对类进行多重继承——这在 C++ 中是允许的。通过接口,多重继承的精髓得以实现。即你的子类可以实现多重接口。(译注:由此可以实现多重继承)
复制内容到剪贴板
using System;
interface myDrawing
int originx
int originy
void Draw(object shape);
class Shape: myDrawing
int OriX;
int OriY;
public int originx
return OriX;
OriX = value;
public int originy
return OriY;
OriY = value;
public void Draw(object shape)
... // 做要做的事
// 类自身的方法
public void MoveShape(int newX, int newY)
.....
数组在 C# 中比 C++ 中要高级很多。数组分配于堆中,所以是引用类型的。你不能访问数组边界外的元素。所以 C# 防止你引发那种 bug。同时也提供了迭代数组元素的帮助函数。foreach 是这样的迭代语句之一。C++ 和 C# 数组的语法差异在于:
方括号在类型后面而不是在变量名后面
创建元素使用 new 运算符
C# 支持一维、多维和交错数组(数组的数组)
复制内容到剪贴板
int[] array = new int[10]; // int 型一维数组
for (int i = 0; i < array.Length; i++)
array = i;
int[,] array2 = new int[5,10]; // int 型二维数组
array2[1,2] = 5;
int[,,] array3 = new int[5,10,5]; // int 型三维数组
array3[0,2,4] = 9;
int[][] arrayOfarray = new int[2]; // int 型交错数组 - 数组的数组
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};
索引器用于书写一个可以通过使用 [] 像数组一样直接访问集合元素的方法。你所需要的只是指定待访问实例或元素的索引。索引器的语法和类属性语法相同,除了接受作为元素索引的输入参数外。
注意:CollectionBase 是用于建立集合的库类。List 是 CollectionBase 中用于存放集合列表的受保护成员。
复制内容到剪贴板
class Shapes: CollectionBase
public void add(Shape shp)
List.Add(shp);
//indexer
public Shape this[int index]
get {
return (Shape) List[index];
set {
List[index] = value ;
装箱/拆箱
装箱的思想在 C# 中是创新的。正如前面提到的,所有的数据类型,无论是内建的还是用户定义的,都是从 System 命名空间的基类 object 继承的。所以基础的或是原始的类型打包为一个对象称为装箱,相反的处理称为拆箱。
复制内容到剪贴板
class Test
static void Main()
int myInt = 12;
object obj = myInt ; // 装箱
int myInt2 = (int) obj; // 拆箱
例程展示了装箱和拆箱两个过程。一个 int 值可以被转换为对象,并且能够再次转换回 int。当某种值类型的变量需要被转换为一个引用类型时,便会产生一个对象箱保存该值。拆箱则完全相反。当某个对象箱被转换回其原值类型时,该值从箱中拷贝至适当的存储空间。
C# 中的参数有三种类型:
1. 按值传递/输入参数
2. 按引用传递/输入-输出参数
3. 输出参数
如果你有 COM 接口的思想,而且还是参数类型的,你会很容易理解 C# 的参数类型。
按值传递/输入参数
值参数的概念和 C++ 中一样。传递的值复制到了新的地方并传递给函数。
复制内容到剪贴板
SetDay(5);
void SetDay(int day)
按引用传递/输入-输出参数
C++ 中的引用参数是通过指针或引用运算符 & 传递的。C# 中的引用参数更不易出错。你可以传递一个引用地址,你传递一个输入的值并通过函数得到一个输出的值。因此引用参数也被称为输入-输出参数。
你不能将未初始化的引用参数传递给函数。C# 使用关键字 ref 指定引用参数。你同时还必须在传递参数给要求引用参数的函数时使用关键字 ref。
复制内容到剪贴板
int a= 5;
FunctionA(ref a); // 使用 ref,否则将引发编译时错误
Console.WriteLine(a); // 打印 20
复制内容到剪贴板
void FunctionA(ref int Val)
int x= Val;
Val = x* 4;
输出参数是只从函数返回值的参数。输入值不要求。C# 使用关键字 out 表示输出参数。
复制内容到剪贴板
int Val;
GetNodeValue(Val);
复制内容到剪贴板
bool GetNodeValue(out int Val)
Val = value;
return true;
参数和数组的数量变化
C# 中的数组使用关键字 params 进行传递。一个数组类型的参数必须总是函数最右边的参数。只有一个参数可以是数组类型。你可以传送任意数量的元素作为数组类型的参数。看了下面的例子你可以更好的理解:
注意:使用数组是 C# 提供用于可选或可变数量参数的唯一途径。
复制内容到剪贴板
void Func(params int[] array)
Console.WriteLine("number of elements {0}", array.Length);
复制内容到剪贴板
Func(); // 打印 0
Func(5); // 打印 1
Func(7,9); // 打印 2
Func(new int[] {3,8,10}); // 打印 3
int[] array = new int[8] {1,3,4,5,5,6,7,5};
Func(array); // 打印 8
运算符与表达式
运算符和表达式跟 C++ 中完全一致。然而同时也添加了一些新的有用的运算符。有些在这里进行了讨论。
is 运算符
is 运算符是用于检查操作数类型是否相等或可以转换。is 运算符特别适合用于多态的情形。is 运算符使用两个操作数,其结果是布尔值。参考例子:
复制内容到剪贴板
void function(object param)
if(param is ClassA)
//做要做的事
else if(param is MyStruct)
//做要做的事
as 运算符
as 运算符检查操作数的类型是否可转换或是相等(as 是由 is 运算符完成的),如果是,则处理结果是已转换或已装箱的对象(如果操作数可以装箱为目标类型,参考 装箱/拆箱)。如果对象不是可转换的或可装箱的,返回值为 null。看看下面的例子以更好的理解这个概念。
复制内容到剪贴板
Shape shp = new Shape();
Vehicle veh = shp as Vehicle; // 返回 null,类型不可转换
Circle cir = new Circle();
Shape shp = cir;
Circle cir2 = shp as Circle; //将进行转换
object[] objects = new object[2];
objects[0] = "Aisha";
object[1] = new Shape();
string str;
for(int i=0; i&< objects.Length; i++)
str = objects as string;
if(str == null)
Console.WriteLine("can not be converted");
Console.WriteLine("{0}",str);
复制内容到剪贴板
Output:
Aisha
can not be converted
除了些许附加的新语句和修改外,C# 的语句和 C++ 的基本一致。
以下是新的语句:
foreach
用于迭代数组等集合。
复制内容到剪贴板
foreach (string s in array)
Console.WriteLine(s);
在线程中使代码块称为重点部分。
(译注:lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。)
checked/unchecked
用于数字操作中的溢出检查。
复制内容到剪贴板
int x = Int32.MaxValue; x++; // 溢出检查
x++; // 异常
unchecked
x++; // 溢出
下面的语句已修改:(译注:原文如此,疑为作者笔误)
Switch
Switch 语句在 C# 中修改过。
1.现在在执行一条 case 语句后,程序流不能跳至下一 case 语句。之前在 C++ 中这是可以的。
复制内容到剪贴板
int var = 100;
switch (var)
case 100: Console.WriteLine(""); // 这里没有 break
case 200: Console.WriteLine(""); break;
C++ 的输出:
复制内容到剪贴板
而在 C# 中你将得到一个编译时错误:
复制内容到剪贴板
error CS0163: Control cannot fall through
from one case label ('case 100:') to another
2.然而你可以像在 C++ 中一样这么用:
复制内容到剪贴板
switch (var)
case 100:
case 200: Console.WriteLine("100 or 200"); break;
3.你还可以用常数变量作为 case 值:
复制内容到剪贴板
const string WeekEnd = "Sunday";
const string WeekDay1 = "Monday";
string WeekDay = Console.ReadLine();
switch (WeekDay )
case WeekEnd: Console.WriteLine("It's weekend!!"); break;
case WeekDay1: Console.WriteLine("It's Monday"); break;
委托让我们可以把函数引用保存在变量中。这就像在 C++ 中使用 typedef 保存函数指针一样。
委托使用关键字 delegate 声明。看看这个例子,你就能理解什么是委托:
复制内容到剪贴板
delegate int Operation(int val1, int val2);
public int Add(int val1, int val2)
return val1 + val2;
public int Subtract (int val1, int val2)
return val1- val2;
public void Perform()
Operation Oper;
Console.WriteLine("Enter + or - ");
string optor = Console.ReadLine();
Console.WriteLine("Enter 2 operands");
string opnd1 = Console.ReadLine();
string opnd2 = Console.ReadLine();
int val1 = Convert.ToInt32 (opnd1);
int val2 = Convert.ToInt32 (opnd2);
if (optor == "+")
Oper = new Operation(Add);
Oper = new Operation(Subtract);
Console.WriteLine(" Result = {0}", Oper(val1, val2));
继承与多态
C# 只允许单一继承。多重继承可以通过接口达到。
复制内容到剪贴板
class Parent{
class Child : Parent
虚函数在 C# 中同样是用于实现多态的概念的,除了你要使用 override 关键字在子类中实现虚函数外。父类使用同样的 virtual 关键字。每个重写虚函数的类都使用 override 关键字。(译注:作者所说的“同样”,“除……外”都是针对 C# 和 C++ 而言的)
复制内容到剪贴板
class Shape
public virtual void Draw()
Console.WriteLine("Shape.Draw") ;
class Rectangle : Shape
public override void Draw()
Console.WriteLine("Rectangle.Draw");
class Square : Rectangle
public override void Draw()
Console.WriteLine("Square.Draw");
class MainClass
static void Main(string[] args)
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Output:
Shape.Draw
Rectangle.Draw
Square.Draw
使用“new”隐藏父类函数
你可以隐藏基类中的函数而在子类中定义其新版本。关键字 new 用于声明新的版本。思考下面的例子,该例是上一例子的修改版本。注意输出,我用 关键字 new 替换了 Rectangle 类中的关键字 override。
复制内容到剪贴板
class Shape
public virtual void Draw()
Console.WriteLine("Shape.Draw") ;
class Rectangle : Shape
public new void Draw()
Console.WriteLine("Rectangle.Draw");
class Square : Rectangle
//这里不用 override
public new void Draw()
Console.WriteLine("Square.Draw");
class MainClass
static void Main(string[] args)
Console.WriteLine("Using Polymorphism:");
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Console.WriteLine("Using without Polymorphism:");
rect.Draw();
Square sqr = new Square();
sqr.Draw();
Output:
Using Polymorphism
Shape.Draw
Shape.Draw
Shape.Draw
Using without Polymorphism:
Rectangle.Draw
Square.Draw
多态性认为 Rectangle 类的 Draw 方法是和 Shape 类的 Draw 方法不同的另一个方法,而不是认为是其多态实现。所以为了防止父类和子类间的命名冲突,我们只有使用 new 修饰符。
注意:你不能在一个类中使用一个方法的两个版本,一个用 new 修饰符,另一个用 override 或 virtual。就像在上面的例子中,我不能在 Rectangle 类中增加另一个名为 Draw 的方法,因为它是一个 virtual 或 override 的方法。同样在 Square 类中,我也不能重写 Shape 类的虚方法 Draw。
调用基类成员
如果子类的数据成员和基类中的有同样的名字,为了避免命名冲突,基类成员和函数使用 base 关键字进行访问。看看下面的例子,基类构造函数是如何调用的,而数据成员又是如何使用的。
复制内容到剪贴板
public Child(int val) :base(val)
myVar = 5;
base.myVar;
public Child(int val)
base(val);
myVar = 5 ;
base.myVar;
本文仅仅是作为 C# 语言的一个快速浏览,以便你可以熟悉该语言的一些特性。尽管我尝试用实例以一种简短而全面的方式讨论了 C# 几乎所有的主要概念,但我认为还是有很多内容需要增加和讨论的。
以后,我会增加更多的没有讨论过的命令和概念,包括事件等。我还想给初学者写一下怎么用 C# 进行 Windows 编程。
参考文献:
我们都知道的 MSDN
Tom Archer 著,Inside C#
Eric Gunnerson 著,A Programmer's Introduction to C#
Karli Watson 著,Beginning C#
O'Reilly(奥莱利出版),Programming C#
2003年6月12日:按引用传递/输入-输出参数一节中增加了 ref 关键字
2003年6月20日:为可选参数增加了一条注意事项,纠正了交错数组例子中赋值运算符的笔误
本文及其任何关联的源代码和文件均以 The Code Project Open License (CPOL)执行。(译注:代码计划网站公开许可)
前言 今天逛了下论坛,发现有一种说法,集合不能存储基本类型,都是存储对象,我自己实验了下,List<int>报错了,而List<Integer>则通过了编译。行吧,暂且认同这种说法。 本篇主要是说明集合中存入对象的问题。对象存入集合都是以内存地址的形式存入,当存入之后,修改了对象的值,就算没有直接操作对象,那么对象里的值也会改变。案例1List中存入Map集合对...
java的容器中可以放基本的数据类型,但是是以包装类的形式,如int 在 容器中是先包装成Integer,再转变成Object存放。集合中也可以放类的实例化对象。
任何一种数据类型或者对象放进容器中后都会失去原有的类型,变成 Object,用的时候从容器中取出后进行转型成所需的类型就可以了,《Think in java》 中是这样解释的: 由于当初编写集合时,那个集合的程序员根本不知道用
集合引用类型:Object、Array(创建数组,数组空位,数组索引,检测数组,迭代器方法,复制和填充方法,转换方法,栈方法,队列方法,排序方法,操作方法,搜索和位置方法,迭代方法,归并方法)、定型数组(ArrayBuffer,DataView)、Map(基本API,Object 与 Map 对比,get(),set(),delete(),clear())、WeakMap、Set、WeakSet使用弱映射
下面分别看一下修改对象属性值和修改对象引用后的效果。
案例一,修改对象属性值
创建几个对象,添加到List中,然后修改对象的属性值,那么List中的元素的属性值会随之改变,比如下面的例子:
public static void test1() {
List<Order> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Order o
前言集合作为一种存储数据的容器,是我们日常开发中使用最频繁的对象类型之一。 在面试中我们经常被问到 ArrayList 和 LinkedList 的区别。相信大部分同学都能回上:“ArrayList 是基于数组实现,LinkedList 是基于链表实现。相应地,也就是说在新增、删除元素时,LinkedList 的效率要高于 ArrayList,而在遍历的时候,ArrayList 的效率要高于 Li...
1.请说出ArrayList、Vector、LinkedList的存储性能和特性。
ArrayList底层 数组结构,线程不安全 线程异步 效率高 查找快 增加删除慢
Vector、底层数组结构 线程同步 线程安全 效率低 存储的是键值对
LinkedList :底层双向链表结构 查找慢 增加删除快 线程异步,不安全,效率高
2.数组有没有length()这个方法?String有没有leng...
//导入的包。import java.util.ArrayList;//用集合存储对象,遍历集合,取所有元素。 用get方法。//创建的一个类。public class zylx4 {//公共静态的主方法。 public static void main(String[] args){ //创建集合。 ArrayList<Integer> array ...