永才 的个人资料守候爱日志列表留言簿更多 工具 帮助

日志


10月1日

放假啦!

终于放假了,再不来个长假让我休息下,我估计真的要崩溃了。。。
 
但是郁闷的是好不容易放假了,但是早上却睡不着了,还是往常一样7点钟准时醒来,但是不同的是往常还想睡,但是今天却一点也不想睡,唉,真是犯贱了。
 
上午看完阅兵式,中午和同学吃了个午饭,下午就无所事事了,我该做什么呢?
 
哈哈,就这样无所事事吧,先祝大家中秋快乐!
9月27日

How in feel

已经连续快一个月没有周末双休了,不过今天还好,心里总是想着还有几天就可以彻底放松下了,晚上也不用加班(实际上晚上还是加了一会),心里就不那么紧绷着了。
国庆节会轻松吗?想想回来后就要有两场重要的考试,一场编程2级考试,一场敏捷考试,都是要命的考试。
 
什么时候才能彻底放松下,不带负担,不带压力的工作呢?
 
只能说,
   feel so bad....
9月23日

好久没更新了

好久没更新了,以后我要经常写点东西,不然不要说历史,哪怕短短几年时间,一些美好的东西也会遗忘,就当未来的回忆录看了。
其实这么长的时间,回忆起来,确实没有任何心得,没有获取,也没有付出,我不喜欢的这样的生活。
不过倒是静下心来,读了许多书,大学毕业后,就再也没有这么静心读书过了,也是一种奢侈的享受吧!
6月15日

[转帖]高考0分作文——这孩子太有才了!

 

作文题目:“细雨湿衣看不见,闲花落地听无声”是唐朝诗人刘长卿在《别严士元》中的诗句。曾经有人这样理解这句诗:1、这是歌颂春天的美好意境。2、闲花、细雨表达了不为人知的寂寞。3、看不见、听不见不等于无所作为,是一种恬淡的处世之道。 4、这种意境已经不适合当今的世界……根据你的看法写一篇作文。题目自拟,体裁不限。字数800以上。

盛夏,夜,深夜。

景山山颠。

山上有人,两个人,一男一女。

这两人就是当今武林名声最响的两位杀手,男的名秋细雨,女的叫叶闲花,江湖人称“细雨闲花”。

    诗人刘长卿曾用“细雨湿衣看不见,闲花落地听无声”来描述这两个可怕的杀手。细雨湿衣,湿衣的是鲜血;闲花落地,落地的是人头。这两人杀人来无影去无踪,如果他们想杀你,当你还没看到他们人影没听到他们声音的时候,你就已经死了。

秋细雨三天前接到一份帖子,指名要杀叶闲花。事成之后,不但有三百万两冥币,更可以让他在“红楼梦中人”选秀节目中担任曹雪芹的角色!

但是杀死叶闲花比杀死比尔还要困难得多。

江湖中没有一个人清楚叶闲花的武功来历,性格脾气,但是每个人都知道叶闲花的故事。

叶闲花有一双迷人的大眼睛,据说她曾一动不动地瞪死过赵薇和高圆圆,而那一年她才十七岁。

叶闲花声音有如黄莺般幽婉醉人,传说听过她说话后林志玲身体酥麻了整整一年,你说要不要命?

叶闲花轻功独步武林,踏雪无痕,落地无声,号称超过当年青翼蝠王韦一笑。有人见她上星期在高速公路上偷了刘翔奥运会入场证,刘翔追出一万公里最后被活活累倒。

一般人听到叶闲花的故事早就吓得去买尿不湿了,但是秋细雨没有去买。

秋细雨不是一般人。

他知道,杀人不但要靠技术,还要拼人品!

秋细雨很镇定,他正用一把指甲刀修整着手指甲,他的手指修长有力。

他要等待,等待对方先沉不住气。高手相争,不允许一丝一毫的失误,先沉不住气的人就会露出破绽。

致命的破绽!

因此秋细雨一言不发,只是静静地玩弄着指甲刀。

没想到叶闲花更是好整以暇,自己悠然自得地涂口红,喷香水。

秋细雨只好先发制人,道:“你知道我找你出来是为什么。”

叶闲花温柔道:“在我们动手之前,不能先谈谈么?”

秋细雨道:“我是来杀人的,不是来聊天的。”

叶闲花道:“你有把握杀我?”

秋细雨道:“我从不做没有把握的事情。”

叶闲花道:“我要提醒你一件事。”

秋细雨道:“你说。”

叶闲花道:“百晓生作杀手谱,小女子是杀手榜排名第一,阁下区区第二,你真能杀得了我么?”

秋细雨道:“我也要提醒你一件事。”

叶闲花道:“你说。”

秋细雨道:“论杀手实力,我本在你之前,只是那次排名百晓生采用了短信投票系统,中国‘花痴’人数过于庞大才让你得了第一。”

叶闲花的脸色一变,道:“我更要提醒你,我的粉丝团叫‘花粉’,不叫‘花痴’!”

秋细雨道:“我最后要提醒你,你的那些‘花粉’全都是花痴。还有,我们已经跑题了。”

叶闲花道:“我们这样拼命厮杀,你难道不怕麻烦么?”

秋细雨道:“你以后再也不用怕麻烦了,天下只有一种人永远不怕麻烦,死人!”

叶闲花道:“这么说你非逼我出手不可?”

秋细雨没有回答,他已不用回答。

秋细雨道:“亮兵器!”

叶闲花道:“我用刀。”

秋细雨道:“你用刀?刀在何处?”

叶闲花道:“我就是刀!”

叶闲花露出甜甜的笑容,忽然间褪下了自己的衣服,全身上下只剩下蕾丝比基尼和黑色丝袜。

叶闲花的脸美得让人窒息,再配上这样的身材,这样的服饰,充满了一种原始的诱惑力。

她的眼睛会说话,她的媚笑会说话,她的手,她的胸膛,她的腿……她身上每分每寸都会说话。

她知道,只要是个不瞎的男人,现在肯定会被她迷得神魂颠倒。

秋细雨是个男人,而且是个不瞎的男人。

可他现在却偏偏好像瞎了一样,完全无动于衷。

他知道,美丽的女人是一把刀,当你沉醉的时候,刀就会切进你的胸口。

秋细雨沉吟道:“我只想问你一件事。”

叶闲花娇笑着:“请讲。”

秋细雨道:“大夏天的,穿这么少你丫不怕蚊子叮啊?”

叶闲花沉默了半晌,幽幽地道:“你一定以为刚才我在喷香水,是不是?我告诉你,我喷的是六神花露水!”

叶闲花又道:“不过这不是普通的六神,是我特别提炼的药水,无色无味无毒,不过却会慢慢扩散在空气中,闻到它的人会四肢麻痹不能动弹。”

秋细雨一惊,忽然觉得身体已经麻木不听使唤,不由得一身冷汗。

叶闲花又道:“你以为我和你扯淡是因为我害怕,以为我脱掉衣服是想**你,其实这都是为了拖延时间让药水能扩散到你周围。”

秋细雨面上不动声色,道:“难道你自己不怕药水的厉害?”

叶闲花得意地道:“一开始我涂的口红就是解药,所以我仍然可以自由行动。”

叶闲花逼视着秋细雨,问道:“现在你还认为你能杀了我么?”

秋细雨道:“我能。”

叶闲花道:“你不能动而我能动,你却能杀了我,这不是很好笑么?”

秋细雨道:“是很好笑,但是你一定会被我杀死。”

叶闲花道:“为什么我会被你杀死?”

秋细雨忽然反问道:“飞刀能不能杀人?”

叶闲花道:“好像能。”

秋细雨道:“我有没有手?”

叶闲花道:“的确有。”

秋细雨道:“我手上有没有刀?”

叶闲花道:“你手上好像只有指甲刀。”

秋细雨道:“足够了。”

叶闲花道:“足够了?”

秋细雨道:“我有手有刀,就能置人死地。”

叶闲花道:“指甲刀也能杀人?实在可笑!”

秋细雨道:“以前江湖中有七十三个人觉得我这把指甲刀很可笑。”

叶闲花道:“现在呢?”

秋细雨道:“现在人都已死了,死在这把刀下。”

叶闲花道:“你的手还能动?”

秋细雨道:“你要不要试试?”

 叶闲花脸上的笑容渐渐凝固,忽然间,她已出手!

一招“冒牌九阴白骨爪”直逼秋细雨天灵盖,这一招她已练过七年四个月零二十九天,她完全有把握相信没有任何人可以抵挡得了这一招。

可这一次她错了。

刀光一闪,“盗版小李飞刀”已插入她的咽喉。

她到死也不相信,一把指甲刀可以要了她的命!

闲花终于落地!

三个时辰后,药水的药效渐渐淡去,秋细雨终于可以动弹了。

望着叶闲花的尸体,秋细雨道:“虽然你已经死了,但是我还要告诉你两件事。第一,我一直用甲刀修整着手指甲是为了调整手和刀之间的同步率,说白了就是找手感。第二,我杀你的真正目的不是为了钱或者名利。”

 一边说,秋细雨一边从叶闲花衣服的口袋里搜出了刘翔的奥运会入场证。

秋细雨坚定地说:“我爱北京,我要看奥运!”

从此,再也没有人见过秋细雨

9月3日

转帖:C和C++编程和学习文档(二)

二、 利用VC++编程实现程序自动启动的编程实例。
  微软公司提供的VC++ 6.0程序开发工具功能非常强大。在VC++ 6.0中同时具有对注册表和*.INI文件操作的函数。笔者经过一段时间的摸索,成功的利用VC++ 6.0开发成功了一个小软件,该软件利用系统自动启动程序的原理,将原来需要的繁琐的手动工作转变成成计算机的自动设置工作,使系统自动启动相关程序的设置工作变的非常简单可靠。
1.程序功能概述:
  程序的主界面是对话框,在主界面对话框中有编辑框(EDIT BOX),圆形按钮(RADIO BUTTON)和普通按钮(COMMON BUTTON)组成。操作者通过向编辑框中添加需要自动加载的程序的全文件名(也可以通过浏览按钮来完成),然后通过对两个RADIO BUTTON的选择,进而完成对加载方式的选择(是选用注册表方式还是选者修改WIN.INI文件的方式),最后操作者通过点击"应用"按钮实现程序的自动加载功能,同时系统会提示操作者是否将操作计算机重新启动,以便观察程序的具体功能完成情况。程序在WIN98中调试运行正常。
2.编码说明:
① 浏览按钮的功能代码:
void CAutoloadDlg::OnLiulan()
{
// TODO: Add your control notification handler code here
CFileDialog fileDlg(TRUE,_T("EXE"),_T("*.exe"),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,(_T("Executable Files (*.exe) |*.exe ||")));//显示打开文件的对话框
if(fileDlg.DoModal()==IDOK)//当操作者选择OK时,程序,取得选择文//件的全路径名(包括文件的路径及文件名称),并将相应的数值传输给相//关的控件变量
{
m_filename=fileDlg.GetPathName();//m_filename是EDIT BOX控件的相应的变量。
UpdateData(FALSE);//向将变量中的数值传输给控件显示出来。
}
② 应用按钮的功能代码:
void CAutoloadDlg::OnOK()
{
// TODO: Add extra validation here
LPCTSTR title;
UpdateData(TRUE);
if(m_title.IsEmpty())//如果操作者没有填写要设置项的标题,程序显示对话框,提示操作者进行相关的填写。
{
MessageBox(_T("Please input the title name"));
return;
}
title=m_title;
if(m_filename.IsEmpty())//如果操作者没有选择要设置的程序的全路径文//件名,程序显示对话框,提示操作者进行相关的选择。
{
MessageBox(_T("Please input the programe file name"));
return;
}
if(IsDlgButtonChecked(IDC_RADIO1))//如果操作者选择注册表方式,程序修改系统的注册表。
{
HKEY hKey;
LPCTSTR data_Set="SoftwareMicrosoftWindowsCurrentVersionRun";//设置注册表中相关的路径
Longret0=(::RegOpenKeyEx(HKEY_LOCAL_MACHINE,data_Set,0,KEY_WRITE,&hKey));//打开注册表中的相应项
if(ret0!=ERROR_SUCCESS)
{
MessageBox("错误0");
}
int length=m_filename.GetLength()+1;//将控件中的内容进行转换,以达到注册表修改函数的参数调用需求。
for(int i=0;i){
if(m_filename[i]==92)
length=length+1;
}
DWORD cbData=length;
LPBYTE lpb=new BYTE[length];
int j=0;
for(i=0;i{
if(m_filename[i]==92)
{
lpb[j]=92;
j++;
lpb[j]=92;
j++;
}
else
{
lpb[j]=m_filename[i];
j++;
}
}
lpb[j]=0;
long ret1=(::RegSetValueEx(hKey,title,NULL,REG_SZ,lpb,cbData));//将相关的信息写入注册表。
if(ret1!=ERROR_SUCCESS)//判断系统的相关注册是否成功?
{
MessageBox("错误1");
}
delete lpb;
::RegCloseKey(hKey);//关闭注册表中的相应的项
}
if(IsDlgButtonChecked(IDC_RADIO2))//如果操作者选择用修改WIN.INI文件的方式
{
LPCTSTR filename;
filename=m_filename;
WritePrivateProfileString(_T("windows"),_T("load"),filename,_T("c:windowswin.ini"));
WritePrivateProfileString(_T("windows"),_T("run"),filename,_T("c:windowswin.ini"));
}
yzdlg.DoModal();//显示对话框,提示操作者是否需要重新启动计算机,以便验证程序的功能。
CDialog::OnOK();
}
③ 重新启动按钮的功能代码:
void yanzheng::OnOK()
{
OSVERSIONINFO OsVerInfo;//保存系统版本信息的数据结构
OsVerInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&OsVerInfo);//取得系统的版本信息
if(OsVerInfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
{
ExitWindowsEx(EWX_REBOOT,0);//重新启动计算机
}
CDialog::OnOK();
}
31.获得本机的地址,机器名,IP……:
#include <winsock.h>
#include <wsipx.h>
#include <wsnwlink.h>
#include <stdio.h>
 
 
int main()
{
       ////////////////
       // 初始化 Windows sockets API. 要求版本为 version 1.1
       //
       WORD wVersionRequested = MAKEWORD(1, 1);
       WSADATA wsaData;
       if (WSAStartup(wVersionRequested, &wsaData)) {
              printf("WSAStartup failed %s\n", WSAGetLastError());
              return -1;
       }
      
       //////////////////
       // 获得主机名.
       //
       char hostname[256];
       int res = gethostname(hostname, sizeof(hostname));
       if (res != 0) {
              printf("Error: %u\n", WSAGetLastError());
              return -1;
       }
       printf("hostname=%s\n", hostname);
       ////////////////
       // 根据主机名获取主机信息.
       //
       hostent* pHostent = gethostbyname(hostname);
       if (pHostent==NULL) {
              printf("Error: %u\n", WSAGetLastError());
              return -1;
       }
       //////////////////
       // 解析返回的hostent信息.
       //
       hostent& he = *pHostent;
       printf("name=%s\naliases=%s\naddrtype=%d\nlength=%d\n",
              he.h_name, he.h_aliases, he.h_addrtype, he.h_length);
      
       sockaddr_in sa;
       for (int nAdapter=0; he.h_addr_list[nAdapter]; nAdapter++) {
              memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[nAdapter],he.h_length);
              // 输出机器的IP地址.
              printf("Address: %s\n", inet_ntoa(sa.sin_addr)); // 显示地址串
       }
       //////////////////
       // 终止 Windows sockets API
       //
       WSACleanup();
       return 0;
}    
32.一个对系统进行“恶作剧”的注册表应用程序段:
         //////////////////////////////////////////////////////////////////////////
       //
       //     Author: hongweijin(robocode_java@163.com)
 
       UpdateData(true);
      
       HKEY hKey;
       //
       //     设置注册表中相关的路径
       //
       LPCTSTR data_Set = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";
       //
       //     RegOpenKeyEx:的函数参数的设置,对read方式没有进行出错检查,
       //     在下面可以看到出错检查
       //    
       DWORD   Souce_Data = 1024;
       LPBYTE  data_Set2  = new BYTE[100];
       DWORD   typeClient = REG_SZ;
 
       RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey);
       //
       //     查询当前的键值有没有存在,若存在讲不写注册表
       //
       long retSec =  (::RegQueryValueEx(hKey,
                                   "LTSMMSGL", NULL, &typeClient,  data_Set2, &Souce_Data));
      
       //
       //     假如ERROR_SUCCESS成立,即找到有这样的值,那么就不去执行下面的程序块
       //     若不成立,那么下面是如何去写一个自动执行的注册表实现
       //
       if (retSec != ERROR_SUCCESS)
       {
              //
              //     先关掉当前以KEY_READ方式打开的注册表
              //
              RegCloseKey(hKey);
              //
              //     打开注册表中的相应项
              //
              long ret0 = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_WRITE, &hKey));
             
              if(ret0 != ERROR_SUCCESS)
                     MessageBox("我靠!啥机子这么强!注册表也禁掉了?");
              //
              //     设置的键名
              //
              LPCTSTR title = "LTSMMSGL";
              //
              //     路径,反正接下来是注销,管它是不是分配的太多。
              //     取当前路径,并对路径进行更改
              //
              char name[3000];
              GetCurrentDirectory(3000, name);
              //////////////////////////////////////////////////////////////////////////
              //_getcwd(name, 1024);
              strcat(name, "\\LTSMMSGL.EXE");
             
              int  strLen   = strlen(name);
              DWORD cbData  = (DWORD)strLen;
              //////////////////////////////////////////////////////////////////////////
              //
              //     将char类型的数据转换为BYTE的格式
              //
              LPBYTE lpb = new BYTE[strLen + 1]; 
              for(int i = 0; i < strLen; i++)
                     lpb[i] = name[i];
              lpb[strLen] = 0;
              //////////////////////////////////////////////////////////////////////////
              //
              //将相关的信息写入注册表。
              //
              long ret1 = (::RegSetValueEx(hKey, title, NULL, REG_SZ, lpb, cbData));
             
              if (ret1 != ERROR_SUCCESS)//判断系统的相关注册是否成功?
                     MessageBox("不会吧!牛比……!");
       }
       RegCloseKey(hKey);
       //////////////////////////////////////////////////////////////////////////
       //     调用系统函数,对系统注销
       //
       BOOL ReStartON = FALSE;
       if (ReStartON == ExitWindowsEx(EWX_LOGOFF, NULL))
              MessageBox("不会吧,怎么回事啊,到底出现了什么问题,快重新启动啊,不然后果俺不负责!");
 
33.对自己的程序服务进行提升:
窗体顶端
不用了,BCB有自己的“服务向导”。
以下的找来的代码。
Windows NT与Windows 9x有一个非常重要的区别,即Windows NT提供了很多功能强大的Service(服务)。这些Service可以随着NT的启动而自启动,也可以让用户通过控制面板启动,还可以被Win32应用程序起停。甚至在没有用户登录系统的情况下,这些Service也能执行。许多FTP、WWW服务器和数据库就是以Service的形式存在于NT上,从而实现了无人值守。就连最新版的“黑客”程序Back Orifice 2000也是以Service形式在NT上藏身的。由于Service的编程较复杂,许多开发者想开发自己的Service但往往都望而却步。鉴于此,下面我们就从头到尾来构造一个全新的Service,读者只要在程序中注明的地方加上自己的代码,那么就可以轻松拥有一个自己的Service。在编写Service之前,先介绍一下几个重要的函数:
     
  ---- 1. SC_HANDLE OpenSCManager( LPCTSTR lpMachineName,
        LPCTSTR lpDatabaseName, DWORD dwDesiredAccess)
     
  ---- OpenSCManager 函数打开指定计算机上的service control
        manager database。其中参数lpMachineName指定计算机名,若为空则指定为本机。LpDatabaseName为指定要打开的service control manager database名, 默认为空。dwDesiredAccess指定操作的权限, 可以为下面取值之一:
     
  ---- SC_MANAGER_ALL_ACCESS //所有权限
     
  ---- SC_MANAGER_CONNECT //允许连接到service control manager database
     
  ---- SC_MANAGER_CREATE_SERVICE //允许创建服务对象并把它加入database
     
  ---- SC_MANAGER_ENUMERATE_SERVICE //允许枚举database 中的Service
     
  ---- SC_MANAGER_LOCK //允许锁住database
     
  ---- SC_MANAGER_QUERY_LOCK_STATUS //允许查询database的封锁信息
     
  ---- 函数执行成功则返回一个指向service control manager
        database的句柄,失败则返回NULL。注意:WINNT通过一个名为service control manager database的数据库来管理所有的Service,因此对Service的任何操作都应打开此数据库。
     
  ---- 2. SC_HANDLE CreateService(SC_HANDLE
        hSCManager,
       LPCTSTR lpServiceName,
 LPCTSTR lpDisplayName, 
 DWORD dwDesiredAccess, 
    DWORD dwServiceType, 
     DWORD dwStartType, 
     DWORD dwErrorControl, 
     LPCTSTR lpBinaryPathName, 
     LPCTSTR lpLoadOrderGroup, 
     LPDWORD lpdwTagId, 
     LPCTSTR lpDependencies, 
     LPCTSTR lpServiceStartName, 
     LPCTSTR lpPassword)
      ---- CreatService函数产生一个新的SERVICE。其中参数hSCManager为指向service
      control manager database 的句柄,由OpenSCManager返回。LpServiceName为SERVICE的名字,lpDisplayName为Service显示用名,dwDesiredAccess是访问权限,本程序中用SERVICE_ALL_ACCESS。wServiceType,指明SERVICE类型,本程序中用SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIVE_PROCESS。dwStartType为Service启动方式,本程序采用自启动,即dwStartType等于SERVICE_AUTO_START。
      dwErrorControl说明当Service在启动中出错时采取什么动作,本程序采用SERVICE_ERROR_IGNORE即忽约错误,读者可以改为其他的。LpBinaryPathName指明Service本体程序的路径名。剩下的五个参数一般可设为NULL。如函数调用成功则返回这个新Service的句柄,失败则返回NULL。与此函数对应的是DeleteService( hService),它删除指定的Service。
     
  ---- 3. SC_HANDLE OpenService(SC_HANDLE hSCManager,LPCTSTR lpServiceName, DWORD dwDesiredAccess )
     
  ---- OpenService函数打开指定的Service。其中参数hSCManager为指向service
        control manager database 的句柄,由OpenSCManager返回。LpServiceName为Service的名字,dwDesiredAccess是访问权限,其可选值比较多,读者可以参看SDK
        Help. 函数调用成功则返回打开的Service句柄,失败则返回NULL。
     
  ---- 4. BOOL StartService( SC_HANDLE hService, DWORD dwNumServiceArgs,LPCTSTR *lpServiceArgVectors )
     
  ---- StartService函数启动指定的Service。其中参数hService 为指向Service的句柄,由OpenService返回。dwNumServiceAr为启动服务所需的参数的个数。lpszServiceArgs
        为 启 动 服务所需的参数。函数执行成功则返回True, 失败则返回False。
     
  ---- 5. BOOL ControlService(SC_HANDLE hService DWORD dwControl,LPSERVICE_STATUS lpServiceStatus )
     
  ---- Service程序没有专门的停止函数,而是用ControlService函数来控制Service的暂停、继续、停止等操作。参数dwControl指定发出的控制命令,可以为以下几个值:
      SERVICE_CONTROL_STOP //停止Service
SERVICE_CONTROL_PAUSE //暂停Service
SERVICE_CONTROL_CONTINUE  //继续Service
SERVICE_CONTROL_INTERROGATE //查询Service的状态
SERVICE_CONTROL_SHUTDOWN  //让ControlService调用失效
      ---- 参数lpServiceStatus是一个指向SERVICE_STATUS的指针。SERVICE_STATUS是一个比较重要的结构,它包含了Service的各种信息,如当前状态、可接受何种控制命令等等。
     
  ---- 6. BOOL QueryServiceStatus( SC_HANDLE hService,LPSERVICE_STATUS lpServiceStatus )
     
  ---- QueryServiceStatus函数比较简单,它查询并返回当前Service的状态。
     
  ---- 编制一个Service一般需要两个程序,一个是Service本体,一个是用于对Service进行控制的控制程序。通常Service本体是一个console程序,而控制程序则是一个普通的Win32应用程序(当然,用户不用控制程序而通过控制面板也可对Service进行启、停,但不能进行添加、删除操作。)
     
  ---- 首先,我们来编写Service本体。对于Service本体来说,它一般又由以下三部分组成:main()、ServiceMain()、Handler(),下面是main()的源代码:(注:由于篇幅的关系,大部分程序都没进行错误处理,读者可以自己添上)
      int main(int argc, char **argv)
{
SERVICE_TABLE_ENTRY ste[2];
//一个Service进程可以有多个线程,这是每个    
//线程的入口表
 ste[0].lpServiceName="W.Z.SERVICE";  //线程名字
 ste[0].lpServiceProc=ServiceMain;
    //线程入口地址
 ste[1].lpServiceName=NULL;
   //最后一个必须为NULL
 ste[1].lpServiceProc=NULL;    
 StartServiceCtrlDispatcher(ste);
    return 0;
}
      ---- main()是Service的主线程。当servie control manager开始一个Service进程时,它总是等待这个Service去调用StartServiceCtrlDispatcher()函数。main(
      )作为这个进程的主线程应该在程序开始后尽快调用StartServiceCtrlDispatcher()。StartServiceCtrlDispatcher()在被调用后并不立即返回,它把本Service的主线程连接到service
      control manager,从而让service control manager通过这个连接发送开始、停止等控制命令给主线程。主线程在这时就扮演了一个命令的转发器的角色,它或者调用Handle( )去处理停止、继续等控制要求,或者产生一个新线程去执行ServiceMain。StartServiceCtrlDispatcher()在整个Service结束时才返回。
     
  ---- ServiceMain()是Service真正的入口点,必须在main()中进行了正确的定义。ServiceMain( )的两个参数是由StartService()传递过来的。下面是ServiceMain()的源代码:
      void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
{
 ssh=RegisterServiceCtrlHandler
("W.Z.SERVICE",Handler);
 ss.dwServiceType=SERVICE_WIN32_OWN
_PROCESS|SERVICE_INTERACTIVE_PROCESS;
ss.dwCurrentState=SERVICE_START_PENDING;
//如用户程序的代码比较多
(执行时间超过1秒),这儿要设成SERVICE_
START_PENDING,待用户程序完成后再设为SERVICE_RUNNING。
 ss.dwControlsAccepted=SERVICE_ACCEPT_
STOP;//表明Service目前能接受的命令是停止命令。
 ss.dwWin32ExitCode=NO_ERROR;
 ss.dwCheckPoint=0;
 ss.dwWaitHint=0;
SetServiceStatus(ssh, &ss);
//必须随时更新数据库中Service的状态。
    Mycode();     //这儿可放入用户自己的代码
 ss.dwServiceType=SERVICE_WIN32_OWN_
PROCESS|SERVICE_INTERACTIVE_PROCESS;
 ss.dwCurrentState=SERVICE_RUNNING;
 ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
 ss.dwWin32ExitCode=NO_ERROR;
 ss.dwCheckPoint=0;
 ss.dwWaitHint=0;
 SetServiceStatus(ssh,&ss);
    Mycode();// 这儿也可放入用户自己的代码
}
在ServiceMain()中应该立即调用
RegisterServiceCtrlHandler()注册一个Handler
去处理控制程序或控制面板对Service的控制要求。
Handler()被转发器调用去处理要求,
下面是Handler()的源代码:
void WINAPI Handler(DWORD Opcode)
{
  switch(Opcode)
  {
    case SERVICE_CONTROL_STOP:  //停止Service
  Mycode();//这儿可放入用户自己的相关代码
        ss.dwWin32ExitCode = 0;
        ss.dwCurrentState  =SERVICE_STOPPED;
//把Service的当前状态置为STOP
        ss.dwCheckPoint    = 0;
        ss.dwWaitHint      = 0;
        SetServiceStatus (ssh,&ss);
 /必须随时更新数据库中Service的状态
        break;
    case SERVICE_CONTROL_INTERROGATE:
SetServiceStatus (ssh,&ss);
 /必须随时更新数据库中Service的状态
        break;
   }
}
      ---- 好了,Service本体程序已基本完成,我们接着来看一下Service的控制程序:
     
  ---- 控制程序是一个标准的window程序,上面主要有四个按纽:Create Service、Delete
        Service、start、stop,分别用来产生、删除、开始和停止Service。下面是它们的部分源代码:
      1. 产生Service
void __fastcall TForm1::CreateBtnClick
(TObject *Sender)
{
    scm=OpenSCManager(NULL,NULL,
SC_MANAGER_CREATE_SERVICE);
 if (scm!=NULL){
  svc=CreateService(scm,
"W.Z.SERVICE","W.Z.SERVICE",//Service名字
SERVICE_ALL_ACCESS,
 SERVICE_WIN32_OWN_PROCESS |SERVICE_INTERACTIVE_PROCESS,
 SERVICE_AUTO_START,       
//以自动方式开始
 SERVICE_ERROR_IGNORE,
 "C:\\ntservice.exe", //Service本体程序路径,
必须与具体位置相符
  NULL,NULL,NULL,NULL,NULL);
        if (svc!=NULL)
 CloseServiceHandle(svc);
  CloseServiceHandle(scm);
    }
}
2. 删除Service
void __fastcall TForm1::DeleteBtnClick
(TObject *Sender)
{
    scm=OpenSCManager(NULL,NULL,
SC_MANAGER_CONNECT);
 if (scm!=NULL){
        svc=OpenService(scm,"W.Z.SERVICE",
SERVICE_ALL_ACCESS);
        if (svc!=NULL){
QueryServiceStatus(svc,&ServiceStatus);
 if (ServiceStatus.dwCurrentState==
SERVICE_RUNNING)//删除前,先停止此Service.
                ControlService(svc,
SERVICE_CONTROL_STOP,&ServiceStatus);
            DeleteService(svc);
            CloseServiceHandle(svc);
 //删除Service后,最好再调用CloseServiceHandle
        }                          
 //以便立即从数据库中移走此条目。
       CloseServiceHandle(scm);
    }
}
3. 开始Service
void __fastcall TForm1::StartBtnClick(TObject *Sender)
{
    scm=OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT);
    if (scm!=NULL){
        svc=OpenService(scm,"W.Z.SERVICE",SERVICE_START);
        if (svc!=NULL){
            StartService(svc,0,NULL);//开始Service
            CloseServiceHandle(svc);
        }
        CloseServiceHandle(scm);
    }
}
4.停止Service
 void __fastcall TForm1::StopBtnClick
(TObject *Sender)
{
    scm=OpenSCManager(NULL,NULL,
SC_MANAGER_ALL_ACCESS);
 if (scm!=NULL){
        svc=OpenService(scm,"W.Z.SERVICE",
SERVICE_STOP|SERVICE_QUERY_STATUS);
        if (svc!=NULL){
            QueryServiceStatus(svc,&ServiceStatus);
            if (ServiceStatus.dwCurrentState==
SERVICE_RUNNING)
                ControlService(svc,
SERVICE_CONTROL_STOP,&ServiceStatus);
            CloseServiceHandle(svc);
        }
        CloseServiceHandle(scm);
    }
}
 
34.预读功能影响媒体文件的删除:
预读机制:
某些媒体播放中断或正在预览时会造成无法删除。在“运行”框中输入:REGSVR32 /U SHMEDIA.DLL,注销掉预读功能。或删除注册表中下面这个键值:[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{87D62D94-71B3-4b9a-9489-5FE6850DC73E}\InProcServer32]。
35.数据类型的转换:
目录
一.              VC常用数据类型列表
二.              常用数据类型转化
2.1数学类型变量与字符串相互转换
2.2 CString及string,char *与其他数据类型的转换和操作
●CString,string,char*的综合比较
●数学类型与CString相互转化
●CString与char*相互转换举例
●CString 与 BSTR 型转换
●VARIANT 型转化成 CString 型
2.3 BSTR、_bstr_t与CComBSTR
2.4 VARIANT 、_variant_t 与 COleVariant
附录CString及字符串转及操作详解
 
参考书籍:CSDN,<<MFC深入浅出(Second Edit)>>
 
 
                             一.VC常用数据类型列表
 
 
 Type
 Default Size
 Description
 
 
 
 
 




 




 
 说明:这些基础数据类型对于MFC还是API都是被支持的
 
boolean
 unsigned 8 bit ,
 取值TRUE/FALSE
 
byte
 unsigned 8 bit,
 整数,输出按字符输出
 
char
 unsigned 8 bit,
 字符
 
double
 signed 64 bit
 浮点型
 
float
 signed32 bit
 浮点型
 
handle_t
 
 Primitive handle type
 
hyper
 signed 64 bit
 整型
 
int
 signed 32 bit
 整型
 
long
 signed 32 bit
 整型
 
short
 signed 16 bit
 整型
 
small
 signed 8 bit
 整型
 
void *
 32-bit
 指向未知类型的指针
 
wchar_t
 unsigned 16 bit
 16位字符,比char可容纳更多的字符
 
 
 
 
 
Win32
API






 



 说明: 这些Win32API支持的简单数据类型主要是用来定义函数返回值,消息参数,结构成员。这类数据类型大致可以分为五大类:字符型、布尔型、整型、指针型和句柄型(?). 总共大概有100多种不同的类型,
 
BOOL/BOOLEAN
 8bit,TRUE/FALSE
 布尔型
 
BYTE
 unsigned 8 bit
 
 
BSTR
CComBSTR
_bstr_t
 32 bit
 BSTR是指向字符串的32位指针
是对BSTR的封装
是对BSTR的封装
 
CHAR
 8 bit
 (ANSI)字符类型
 
COLORREF
 32 bit
 RGB颜色值 整型
 
DWORD
 unsigned 32 bit
 整型
 
FLOAT
 float型
 float型
 
HANDLE
 
 Object句柄
 
HBITMAP
 
 bitmap句柄
 
HBRUSH
 
 brush句柄
 
HCURSOR
 
 cursor句柄
 
HDC
 
 设备上下文句柄
 
HFILE
 
 OpenFile打开的File句柄
 
HFONT
 
 font句柄
 
HHOOK
 
 hook句柄
 
HKEY
 
 注册表键句柄
 
HPEN
 
 pen句柄
 
HWND
 
 window句柄
 
INT
 --------
 --------
 
LONG
 --------
 ---------
 
LONGLONG
 
 64位带符号整型
 
LPARAM
 32 bit
 消息参数
 
LPBOOL
 
 BOOL型指针
 
LPBYTE
 
 BYTE型指针
 
LPCOLOREF
 
 COLORREF型指针
 
LPCSTR/LPSTR/PCSTR
 
 指向8位(ANSI)字符串类型指针
 
LPCWSTR/LPWSTR/PCWSTR
 
 指向16位Unicode字符串类型
 
LPCTSTR/LPTSTR/PCTSTR
 
 指向一8位或16位字符串类型指针
 
LPVOID
 
 指向一个未指定类型的32位指针
 
LPDWORD
 
 指向一个DWORD型指针
 
其他相似类型: LPHANDLE、LPINT、LPLONG、LPWORD、LPRESULT
PBOOL、PBOOLEAN、PBYTE、PCHAR、PDWORD、PFLOAT、PHANDLE、PINT、PLONG、PSHORT……
说明:(1)在16位系统中 LP为16bit,P为8bit,在32位系统中都是32bit(此时等价)
(2)LPCSTR等 中的C指Const,T表示TCHAR模式即可以工作在ANSI下也可UNICODE
 
SHORT
 usigned
 整型
 
其他UCHAR、UINT、ULONG、ULONGLONG、USHORT为无符号相应类型
 
TBYTE
 
 WCHAR型或者CHAR型
 
TCHAR
 
 ANSI与unicode均可
 
VARIANT
_variant_t
COleVariant
 
 一个结构体参考OAIDL.H
_variant_t是VARIANT的封装类
COleVariant也是VARIANT的封装类
 
 
 
 
 
 
 
 
 
WNDPROC
 
 指向一个窗口过程的32位指针
 
WCHAR
 
 16位Unicode字符型
 
WORD
 
 16位无符号整型
 
WPARAM
 
 消息参数
 
MFC
独有
数据
类型
 下面两个数据类型是微软基础类库中独有的数据类型
 
POSITION
 标记集合中一个元素的位置的值,被MFC中的集合类所使用
 
LPCRECT
 指向一个RECT结构体常量(不能修改)的32位指针
 
CString
 其实是MFC中的一个类
 
 
 
 
 
说明:
(1)-------表示省略
(2)1Byte=8Bit,
字与机器有关,在8位系统中:字=1字节,16位系统中,1字=2字节,32位中:1字=4字节,
64位中1字=8字节.不要搞混这些概念.
 
 
二.常用数据类型转化及操作
2.1 数学类型变量与字符串相互转换(这些函数都在STDLIB.H里)
(1)将数学类型转换为字符串可以用以下一些函数:
举例: _CRTIMP char * __cdecl _itoa(int, char *, int);//这是一个将数字转换为一个字符串类型的函数,最后一个int表示转换的进制
如以下程序:
int iTyep=3;
char *szChar;
itoa(iType,szChar,2);
cout<<szChar;//输出为1010
类似函数列表:
_CRTIMP char * __cdecl _itoa(int, char *, int);//为了完整性,也列在其中
_CRTIMP char * __cdecl _ultoa(unsigned long, char *, int);
_CRTIMP char * __cdecl _ltoa(long, char *, int);
_CRTIMP char * __cdecl _i64toa(__int64, char *, int);
_CRTIMP char * __cdecl _ui64toa(unsigned __int64, char *, int);
_CRTIMP wchar_t * __cdecl _i64tow(__int64, wchar_t *, int);
_CRTIMP wchar_t * __cdecl _ui64tow(unsigned __int64, wchar_t *, int);
_CRTIMP wchar_t * __cdecl _itow (int, wchar_t *, int);//转换为长字符串类型
_CRTIMP wchar_t * __cdecl _ltow (long, wchar_t *, int);
_CRTIMP wchar_t * __cdecl _ultow (unsigned long, wchar_t *, int);
还有很多,请自行研究
(2)将字符串类型转换为数学类型变量可以用以下一些函数:
举例: _CRTIMP int  __cdecl atoi(const char *);//参数一看就很明了
char *szChar=”88”;
int temp(0);
temp=atoi(szChar);
cout<<temp;
类似的函数列表:
_CRTIMP int    __cdecl atoi(const char *);
_CRTIMP double __cdecl atof(const char *);
_CRTIMP long   __cdecl atol(const char *);
_CRTIMP long double __cdecl _atold(const char *);
_CRTIMP __int64 __cdecl _atoi64(const char *);
_CRTIMP double __cdecl strtod(const char *, char **);//
_CRTIMP long   __cdecl strtol(const char *, char **, int);//
_CRTIMP long double __cdecl _strtold(const char *, char **);
_CRTIMP unsigned long __cdecl strtoul(const char *, char **, int);
_CRTIMP double __cdecl wcstod(const wchar_t *, wchar_t **);//长字符串类型转换为数学类型
_CRTIMP long   __cdecl wcstol(const wchar_t *, wchar_t **, int);
_CRTIMP unsigned long __cdecl wcstoul(const wchar_t *, wchar_t **, int);
_CRTIMP int __cdecl _wtoi(const wchar_t *);
_CRTIMP long __cdecl _wtol(const wchar_t *);
_CRTIMP __int64   __cdecl _wtoi64(const wchar_t *);
还有很多,请自行研究
2.2.CString及string,char *与其他数据类型的转换和操作
(1)CString,string,char*的综合比较(这部分CSDN上的作者joise的文章
<< CString,string,char*的综合比较>>写的很详细,请大家在仔细阅读他的文章.
地址: http://blog.csdn.net/joise/
或参考附录:
(2)转换:
●数学类型与CString相互转化
 数学类型转化为CString
可用Format函数,举例:
CString s;
int i = 64;
s.Format("%d", i)
CString转换为数学类型:举例
CString strValue("1.234");
double dblValue;
dblValue = atof((LPCTSTR)strValue);
●CString与char*相互转换举例
CString strValue(“Hello”);
char *szValue;
szValue=strValue.GetBuffer(szValue);
也可用(LPSTR)(LPCTSTR)对CString//  进行强制转换. 
szValue=(LPSTR)(LPCTSTR)strValue;
反过来可直接赋值:
char *szChar=NULL;
CString strValue;
szChar=new char[10];
memset(szChar,0,10);
strcpy(szChar,”Hello”);
strValue=szChar;
●CString 与 BSTR 型转换
CString 型转化成 BSTR 型
当我们使用 ActiveX 控件编程时,经常需要用到将某个值表示成 BSTR 类型.BSTR 是一种记数字符串,Intel平台上的宽字符串(Unicode),并且可以包含嵌入的 NULL 字符。
可以调用 CString 对象的 AllocSysString 方法将 CString 转化成 BSTR:
CString str;
str = .....; // whatever
BSTR bStr = str.AllocSysString();
 
BSTR型转换为CString
如果你在 UNICODE 模式下编译代码,你可以简单地写成:
CString convert(BSTR bStr)
{
    if(bStr == NULL)
        return CString(_T(""));
    CString s(bStr); // in UNICODE mode
    return s;
}
如果是 ANSI 模式
CString convert(BSTR b)
{
    CString s;
    if(b == NULL)
       return s; // empty for NULL BSTR
#ifdef UNICODE
    s = b;
#else
    LPSTR p = s.GetBuffer(SysStringLen(b) + 1);
    ::WideCharToMultiByte(CP_ACP,            // ANSI Code Page
                          0,                 // no flags
                          b,                 // source widechar string
                          -1,                // assume NUL-terminated
                          p,                 // target buffer
                          SysStringLen(b)+1, // target buffer length
                          NULL,              // use system default char
                          NULL);             // don''t care if default used
    s.ReleaseBuffer();
#endif
    return s;
}
 
●VARIANT 型转化成 CString 型
VARIANT 类型经常用来给 COM 对象传递参数,或者接收从 COM 对象返回的值。你也能自己编写返回 VARIANT 类型的方法,函数返回什么类型 依赖可能(并且常常)方法的输入参数(比如,在自动化操作中,依赖与你调用哪个方法。IDispatch::Invoke 可能返回(通过其一个参数)一个 包含有BYTE、WORD、float、double、date、BSTR 等等 VARIANT 类型的结果,(详见 MSDN 上的 VARIANT 结构的定义)。在下面的例子中,假设 类型是一个BSTR的变体,也就是说在串中的值是通过 bsrtVal 来引用,其优点是在 ANSI 应用中,有一个构造函数会把 LPCWCHAR 引用的值转换为一个 CString(见 BSTR-to-CString 部分)。在 Unicode 模式中,将成为标准的 CString 构造函数,参见对缺省::WideCharToMultiByte 转换的告诫,以及你觉得是否可以接受(大多数情况下,你会满意的)。VARIANT vaData;
vaData = m_com.YourMethodHere();
ASSERT(vaData.vt == VT_BSTR);
CString strData(vaData.bstrVal);
你还可以根据 vt 域的不同来建立更通用的转换例程。为此你可能会考虑:
CString VariantToString(VARIANT * va)
{
    CString s;
    switch(va->vt)
      { /* vt */
       case VT_BSTR:
          return CString(vaData->bstrVal);
       case VT_BSTR | VT_BYREF:
          return CString(*vaData->pbstrVal);
       case VT_I4:
          s.Format(_T("%d"), va->lVal);
          return s;
       case VT_I4 | VT_BYREF:
          s.Format(_T("%d"), *va->plVal);
       case VT_R8:
          s.Format(_T("%f"), va->dblVal);
          return s;
       ... 剩下的类型转换由读者自己完成
       default:
          ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)
          return CString("");
      } /* vt */
}
 
2.3 BSTR、_bstr_t与CComBSTR
CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。
char *转换到BSTR可以这样:
BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上头文件comutil.h
反之可以使用char *p=_com_util::ConvertBSTRToString(b);
2.4(引)VARIANT 、_variant_t 与 COleVariant
VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:
VARIANT va;
int a=2001;
va.vt=VT_I4;///指明整型数据
va.lVal=a; ///赋值
对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:
unsigned char bVal; VT_UI1
short iVal; VT_I2
long lVal; VT_I4
float fltVal; VT_R4
double dblVal; VT_R8
VARIANT_BOOL boolVal; VT_BOOL
SCODE scode; VT_ERROR
CY cyVal; VT_CY
DATE date; VT_DATE
BSTR bstrVal; VT_BSTR
IUnknown FAR* punkVal; VT_UNKNOWN
IDispatch FAR* pdispVal; VT_DISPATCH
SAFEARRAY FAR* parray; VT_ARRAY|*
unsigned char FAR* pbVal; VT_BYREF|VT_UI1
short FAR* piVal; VT_BYREF|VT_I2
long FAR* plVal; VT_BYREF|VT_I4
float FAR* pfltVal; VT_BYREF|VT_R4
double FAR* pdblVal; VT_BYREF|VT_R8
VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL
SCODE FAR* pscode; VT_BYREF|VT_ERROR
CY FAR* pcyVal; VT_BYREF|VT_CY
DATE FAR* pdate; VT_BYREF|VT_DATE
BSTR FAR* pbstrVal; VT_BYREF|VT_BSTR
IUnknown FAR* FAR* ppunkVal; VT_BYREF|VT_UNKNOWN
IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH
SAFEARRAY FAR* FAR* pparray; VT_ARRAY|*
VARIANT FAR* pvarVal; VT_BYREF|VT_VARIANT
void FAR* byref; VT_BYREF
_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
例如:
long l=222;
ing i=100;
_variant_t lVal(l);
lVal = (long)i;
COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:
COleVariant v3 = "字符串", v4 = (long)1999;
CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;
 
36.匈牙利命名法
 
MFC、句柄、控件及结构的命名规范
Windows类型       样本变量  MFC类    样本变量
HWND    hWnd;  CWnd*   pWnd;
HDLG      hDlg;    CDialog*       pDlg;
HDC       hDC;     CDC*     pDC;
HGDIOBJ       hGdiObj;      CGdiObject*  pGdiObj;
HPEN      hPen;   CPen*    pPen;
HBRUSH hBrush;       CBrush* pBrush;
HFONT   hFont; CFont*   pFont;
HBITMAP       hBitmap;     CBitmap*      pBitmap;
HPALETTE     hPaltte;       CPalette*      pPalette;
HRGN     hRgn;   CRgn*    pRgn;
HMENU hMenu; CMenu* pMenu;
HWND    hCtl;     CState*        pState;
HWND    hCtl;     CButton*      pButton;
HWND    hCtl;     CEdit*    pEdit;
HWND    hCtl;     CListBox*      pListBox;
HWND    hCtl;     CComboBox*       pComboBox;
HWND    hCtl;     CScrollBar*   pScrollBar;
HSZ       hszStr; CString pStr;
POINT    pt; CPoint   pt;
SIZE      size;     CSize     size;
RECT      rect;     CRect     rect;
一般前缀命名规范
前缀 类型 实例
C     类或结构  CDocument,CPrintInfo
m_  成员变量  m_pDoc,m_nCustomers
变量命名规范
前缀 类型 描述 实例
ch    char       8位字符  chGrade
ch   TCHAR    如果_UNICODE定义,则为16位字符   chName
b     BOOL     布尔值     bEnable
n     int   整型(其大小依赖于操作系统)       nLength
n     UINT      无符号值(其大小依赖于操作系统) nHeight
w    WORD    16位无符号值 wPos
l      LONG     32位有符号整型     lOffset
dw DWORD        32位无符号整型     dwRange
p     *     指针 pDoc
lp    FAR*      远指针     lpszName
lpsz       LPSTR    32位字符串指针     lpszName
lpsz       LPCSTR 32位常量字符串指针      lpszName
lpsz       LPCTSTR       如果_UNICODE定义,则为32位常量字符串指针  lpszName
h     handle   Windows对象句柄 hWnd
lpfn        callback  指向CALLBACK函数的远指针      
应用程序符号命名规范
前缀 符号类型  实例 范围
IDR_      不同类型的多个资源共享标识   IDR_MAIINFRAME 1~0x6FFF
IDD_      对话框资源      IDD_SPELL_CHECK     1~0x6FFF
HIDD_    对话框资源的Help上下文       HIDD_SPELL_CHECK 0x20001~0x26FF
IDB_      位图资源  IDB_COMPANY_LOGO        1~0x6FFF
IDC_      光标资源  IDC_PENCIL        1~0x6FFF
IDI_       图标资源  IDI_NOTEPAD      1~0x6FFF
ID_  来自菜单项或工具栏的命令      ID_TOOLS_SPELLING        0x8000~0xDFFF
HID_      命令Help上下文     HID_TOOLS_SPELLING      0x18000~0x1DFFF
IDP_       消息框提示      IDP_INVALID_PARTNO       8~0xDEEF
HIDP_    消息框Help上下文  HIDP_INVALID_PARTNO     0x30008~0x3DEFF
IDS_       串资源     IDS_COPYRIGHT 1~0x7EEF
IDC_      对话框内的控件       IDC_RECALC        8~0xDEEF
Microsoft MFC宏命名规范
名称 类型
_AFXDLL 唯一的动态连接库(Dynamic Link Library,DLL)版本
_ALPHA  仅编译DEC Alpha处理器
_DEBUG 包括诊断的调试版本
_MBCS   编译多字节字符集
_UNICODE    在一个应用程序中打开Unicode
AFXAPI   MFC提供的函数
CALLBACK     通过指针回调的函数
库标识符命名法
标识符     值和含义
u     ANSI(N)或Unicode(U)
d     调试或发行:D = 调试;忽略标识符为发行。
静态库版本命名规范
库    描述
NAFXCWD.LIB      调试版本:MFC静态连接库
NAFXCW.LIB  发行版本:MFC静态连接库
UAFXCWD.LIB      调试版本:具有Unicode支持的MFC静态连接库
UAFXCW.LIB  发行版本:具有Unicode支持的MFC静态连接库
动态连接库命名规范
名称 类型
_AFXDLL 唯一的动态连接库(DLL)版本
WINAPI Windows所提供的函数
Windows.h中新的命名规范
类型 定义描述
WINAPI  使用在API声明中的FAR PASCAL位置,如果正在编写一个具有导出API人口点的DLL,则可以在自己的API中使用该类型
CALLBACK     使用在应用程序回叫例程,如窗口和对话框过程中的FAR PASCAL的位置
LPCSTR  与LPSTR相同,只是LPCSTR用于只读串指针,其定义类似(const char FAR*)
UINT       可移植的无符号整型类型,其大小由主机环境决定(对于Windows NT和Windows 9x为32位);它是unsigned int的同义词
LRESULT 窗口程序返回值的类型
LPARAM  声明lParam所使用的类型,lParam是窗口程序的第四个参数
WPARAM       声明wParam所使用的类型,wParam是窗口程序的第三个参数
LPVOID  一般指针类型,与(void *)相同,可以用来代替LPSTR
 
 

转帖:C和C++编程和学习文档

1  :指针变量名称以p为首字符,这是程序员通常在定义指针时的一个习惯
2  :har * p;    (int *)p 把p强制转换为int型                         
3.1 :指针的问题:指针应用时最好给予定义(初始化)这样可以保证指针的指向是程序员自己能够把握的。
3.2 :指针的越界,这恐怕是最难查出的吧!                          
3.3 :指针的局部变量问题。局部的指针变量会被程序自动释放,若程序员引用此类指针就会出错。2007-9-1
4.二维指针的应用实例:
#include <stdio.h>
#include <string.h>
 
void sort(char (*client)[10]);
 
void main()
{
         int temp;
         char client[3][10];
         char (*pClient)[10] = NULL;
 
         for( temp = 0; temp < 3; temp++ )
         {
                   gets(client[temp]);
         }
         pClient = client;
 
    sort(pClient);
 
         for( temp = 0; temp < 3; temp++ )
         {
                   puts(*(pClient + temp));
         }
 
}
 
void sort(char (*client)[10])
{
         //冒泡算法的明了写法
         int temp1, temp2;
         char temp[10];
      for( temp1 = 2; temp1 > 0; temp1-- )//控制每一步的比较次数
         {
                   for( temp2 = 0; temp2 < temp1; temp2++ )//比较指针
                   {
                            if( strcmp (*(client + temp2), *(client + temp2 + 1)) )//比较过程
                            {
                                     strcpy(temp, *(client + temp2));
                                     strcpy(*(client + temp2), *(client + temp2 + 1));
                                strcpy(*(client + temp2 + 1), temp);
                            }
                   }
         }
}
5.类型转换中的结构体:如p = (struct student * )stu[0].name  将p指向结构体的内部元素的地址,要进行类型转换,先转换为p的类型。
6.定义在函数内部的指针结构体是不会被系统释放的。例程:猫和老鼠。
void Insert(struct student *pHeadGet, int numInsert)
{
         struct student *pOne, *pTwo, *pInsert;
         int temp;
 
         pTwo = pOne = pHeadGet;
         for( temp = 0; temp < numInsert - 1; temp++ )
         {
                   pTwo = pTwo->pNext;
         }
         pOne = pTwo->pNext;
         printf("Please into the number and the score:\n");
     pInsert = (struct student *) malloc(LEN);//这个在函数内部开辟的空间在函数调用后还是保留在内存
         scanf("%d%d", &pInsert->number, &pInsert->score);
         pTwo->pNext   = pInsert;
         pInsert->pNext = pOne;
}
7:连接字符的错误写法:
#include <stdio.h>
 
main()
{
         char a[]="wo shi libingbing", b[] = "li jiang ye shi wo";
         char *p1, *p2;
         p1 = a;
         p2 = b;
 
         //*(p1 + 17) = *(p2 +0);
         //(p1 +17) = p2;此处在尝试改变数组的值,这是不允许的
         printf("%s", p1);
 
}
 
8.指针中赋值和修改的一些容易错误和注意的地方
#include <stdio.h>
 
void main()
{
         char amessage[] = "now is the time";
         char *pmessage  = "now is the time";
         int *pInt = {2, 3, 6, 23};//这样的定义是不允许的
 
         *(amessage + 3) = 'H';
//       *(pmessage +3)  = 'H';  不能尝试修改指针定义的字符数组
 
         printf("%s\n%s\n", amessage, pmessage);
        
         pmessage = amessage;
         *(pmessage +3)  = 'h';
        
         printf("%s\n%s\n", amessage, pmessage);//从执行结果可以知道指针只是一种指向,不能达到引用并修改字符串的能力
 
         //       *(pInt + 3) = 8;
//  printf("%d", pInt);
}
9.字符串的操作:
stringDepart()
//讲字符串进行分解成单个单词的形式
//返回打印结果
while (tempChar = GETCHAR != EOF)
{
         if (tempChar == (‘ ’ || ‘\n’ || ‘\t’))
{
         if (STATE == IN)
{
                   // 得到一个单词
                   STATE == OUT;
}
else if (STATE == OUT)
{
         STATE == IN;
         //操作字符
}
else
{
         //操作字符
}/
         }//end if (tempChar == (‘ ’ || ‘\n’ || ‘\t’))
}///stringDepart
10.Stract函数:
   /*strcat function*/
//函数将字符串t接到s中
void strcat(char *s, char *t)
{
         while (*s)
                   s++;
         while(*s++ = *t++)
                   ;
}
11.标准的冒泡排序:
for( times = length - 1; times > 0; times--)   //排序的次数
         for( client = 0; client < times; client++) //控制比较
            if (item[client] > item[client + 1])  //比较交换
                            {
                                     //交换client和client + 1的值
                            }
 
12.用户控制的程序结束:
while(1)
{
//操作代码
if(checkChar = ‘q’ || ‘Q’) return;
//操作代码
}
 
13.用堆栈实现的表达式的计算:
函数算法:
float getnumber(void)
//提取表达式中的一个几位数字,也要判断其格式的正确与否
//输入为void,返回是一个float型数
//用于学习的目的编写的
{
         if (point > strLen -1)  //假如没有任何字符
                   return NULL;
     if  (*(string  + point) == ‘-’)
                   return NULL;
         while (string[point] == '(')
         {
                   if (string[point+1] == '-')
                   {                           //负号
                            point++;
                            return 0;
                   }
                   else if  (*(string  + point+1) == '(')
                            push(0);              //压入栈中,
                   else
                            break;
         }
}
 
14.Main函数的规范写法:
int
main(int argc, char **argv)
 
15.C学习的难易:
学习c有一个学期了,对于c语言这样的一个词汇,有人会发帖问这语言如何?好学?不好学?对于语言本身没有好学与不好学的,而真正主导编程的不是语言而是语言和数据的搭配——数据结构;最这看来我们可能可以得到这样的结论:语言和数据结构没有必要有先后,可以同时学啊,是的这样就使语言有难易之分。
 
16.C++是c的优化:
1.在c++中我们提倡使用const char * const authorName = "Scott Meyers";这样的方式,对于指针我们要使指针本身常量化,也要使指针所指的变量常量化。这就是上面这样做的原因。
2.对于define所造成的混乱:
#define max(a,b) ((a) > (b) ? (a) : (b))
int a = 5, b = 0;
max(++a, b);// a 的值增加了2次
max(++a, b+10); // a 的值只增加了1次
内联函数解决了这个问题:
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }
 
3. string *stringarray1 =static_cast<string*>(malloc(10 * sizeof(string)));
string *stringarray2 = new string[10];
其结果是,stringarray1确实指向的是可以容纳10个string对象的足够空间,但内存里并没有创建这些对象。而且,如果你不从这种晦涩的语法怪圈(详见条款m4和m8的描述)里跳出来的话,你没有办法来初始化数组里的对象。换句话说,stringarray1其实一点用也没有。相反,stringarray2指向的是一个包含10个完全构造好的string对象的数组,每个对象可以在任何读取string的操作里安全使用。
把new和delete与malloc和free混在一起用也是个坏想法。对一个用new获取来的指针调用free,或者对一个用malloc获取来的指针调用delete,其后果是不可预测的。大家都知道“不可预测”的意思:它可能在开发阶段工作良好,在测试阶段工作良好,但也可能会最后在你最重要的客户的脸上爆炸。
如果你调用new时用了[],调用delete时也要用[]。如果调用new时没有用[],那调用delete时也不要用[]。
17.Malloc的一个问题
对于malloc在ANSI C之前的C版本中,还需要用类型转换运算符。
18.预处理问题
C++语法接受#define int INT, integer
19.“,”运算符问题
在c的编译器中”,”运算符是不能做为左值的,但是在c++中解决了这个问题,她可以做左值。
20.关于运算符的一个例子
在不同的编译器下,有些表达式得到的结果是不尽相同的,比如下面的表达式:a = 1 , b = 1;(a * b + ++b);在vc中得到是3, 而在bc中得到的却是1×2+2 = 4。从这个例子可以看出来,运算符之间的优先级是没有特别必要去区分的,像这样的题目要得到不同的运算方式可以采用讲语句分成两个语句,实现起来没什么不爽的。
就如在这样的一个表达式中,++a*(a + b).一般我们会认为括号的运算级别最高,但是错了,先是++a.然后再进入括号运算。呜呼!累,没必要啊,可是有些题目就是这样,悲哉!
21.把二进制转换为十进制的算法表示(用位运算实现)
//以字符型来表示二进制数字,对其进行检测,得到unsign型的int型数据输出。
unsigned long BtoD(char *str)
{
    int i;
    unsigned long m;
    unsigned long n = 0;
    int len = strlen(str);
        
    if (len > 32)
        len = 32;
         m = 0x80000000 >> (32 - len);
         for(i = 0;  i < len; ++i)
    {
        if (str[i] == '1') // 非法字符认作 0
            n |= m;
        m >>= 1;
    }
    return n;
}
22.一道经典题目:关键是速度。
有五位小姐排成一列,所有的小姐姓不同、穿的衣服颜色不同、喝不同的饮料、养不同的宠物、吃不同的水果。
      钱小姐穿红色衣服;翁小姐养了一只狗;陈小姐喝茶;穿绿衣服的站在穿
白衣服的左边;穿绿衣服的小姐喝咖啡;吃西瓜的小姐养鸟;穿黄衣服的小姐吃
梨;站在中间的小姐喝牛奶;赵小姐站在最左边;吃橘子的小姐站在养猫的旁边;
养鱼的小姐旁边的那位吃梨;吃苹果的小姐喝香槟;江小姐吃香蕉;赵小姐站在
穿蓝衣服的小姐旁边;喝开水的小姐站在吃橘子的小姐旁边;请问哪位小姐养蛇?
答案和解析:
本题是柏林大学的一次考试题,要求在30分钟内做出,不过只有少于10%的人完成了要求。计分是这样的,共150分,从1到30分钟,每加1分钟减2分,那么30分钟答出就是90分,是及格分;从30分钟以后每加1分钟减1分。我当时用了22分钟,大家也试试,看自己能得多少分。
赵小姐穿黄色衣服,喝白开水,吃梨,奍猫
陈小姐穿蓝色衣服,喝茶,吃橘子,奍鱼
钱小姐穿红色衣服,喝牛奶,吃西瓜,奍鸟
江小姐穿绿色衣服,喝咖啡,吃香蕉,奍蛇
翁小姐穿白色衣服,喝香槟,吃苹果,奍狗
22.C++中的重载函数的实现:
使用名字粉碎的方式,对不同的函数加以区分。如:int f(char a, int b, float c);编译后就是f_cif();
23.关于临时变量中使用i的看法:
对于代码规范来说使用i作为临时变量也是可取的,用此作为循环变量是可以的。
24.一个字符串常量定义的应用错误:
#include <stdio.h>
#include <string.h>
 
void main()
{
         //这样定义就是指getSource,source指向的是一组字符串常量
         char *source = "China";//改为这样的定义方式就对了:source[] = “China”;
         char *getSource = "Republic of";
 
         printf("%s %s ",getSource, source);                  //可以引用常量,但是不能改变常量
         printf("%s", strcpy(getSource, source));              //执行错误
         printf("%s", strncpy(getSource, source, sizeof(source))); //执行错误
}
25.一个不明白的执行错误:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
26.匈牙利命名法:
windows API的命名法则是匈牙利籍微软专家:查尔斯西蒙尼在博士论文里提出的。
<!--[if !supportLists]-->1.   <!--[endif]-->标示符的名字以一个或者多个小写字母开头,用这些字母来指定数据类型:
前缀
 数据类型
 
 
c
 字符
 
s
 字符串
 
cb
 用于定义对象(一般为一个结构)尺寸的整数
 
n
 整数
 
by
 字节
 
i
 Int(整数)
 
x
 短整数(坐标x)
 
y
 短整数(坐标Y)
 
b
 Boolean(布尔值)
 
w
 字(Word, 焐符号短整数)
 
l
 长整数(long)
 
g
 HANDLE(无符号int)
 
m
 类成员变量
 
fn
 函数(function)
 
dw
 双字(double word,无符号长整形)
 
 
2.其他则从第二个字符起采用“驼峰”命名规则。
 
27.Cstring转换LPBYTE格式:
//////////////////////////////////////////////////////////////////////////
        
         //       将CString转换为LPBYTE
         //
         LPBYTE lpb = new BYTE[name.GetLength()+1]; 
    for(int i = 0; i< name.GetLength();i++)
        lpb[i] = name[i];
    lpb[name.GetLength()] = 0;
//////////////////////////////////////////////////////////////////////////
28.网络编程用的基本函数:
本文所谈到的Socket函数如果没有特别说明,都是指的Windows Socket API。
一、WSAStartup函数
int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);
使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。该函数执行成功后返回0。
例:假如一个程序要使用2.1版本的Socket,那么程序代码如下
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
二、WSACleanup函数
int WSACleanup (void);
  应用程序在完成对请求的Socket库的使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。
三、socket函数
SOCKET socket(
int af,
int type,
int protocol
);
  应用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM;第三个参数指定应用程序所使用的通信协议。
   该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表但是套接字数据结构都是在操作系统的内核缓冲里。下面是一个创建流套接字的例子:
struct protoent *ppe;
ppe=getprotobyname("tcp");
SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppe->p_proto);
四、closesocket函数
int closesocket(
SOCKET s
);
closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。
closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。
五、send函数
int send(
SOCKET s,
const char FAR *buf,
int len,
int flags
);
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。该函数的第一个参数指定发送端套接字描述符;第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
六、recv函数
int recv(
SOCKET s,
char FAR *buf,
int len,
int flags
);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
七、bind函数
int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
当创建了一个Socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。客户程序一般不必调用bind函数来为其Socket绑定IP地址和断口号。该函数的第一个参数指定待绑定的Socket描述符;第二个参数指定一个sockaddr结构,该结构是这样定义的:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,我们通常使用另一个地址结构:
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
其中sin_family置AF_INET;sin_port指明端口号;sin_addr结构体中只有一个唯一的字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr()把字符串形式的IP地址转换成unsigned long型的整数值后再置给s_addr。有的服务器是多宿主机,至少有两个网卡,那么运行在这样的服务器上的服务程序在为其Socket绑定IP地址时可以把htonl(INADDR_ANY)置给s_addr,这样做的好处是不论哪个网段上的客户程序都能与该服务程序通信;如果只给运行在多宿主机上的服务程序的Socket绑定一个固定的IP地址,那么就只有与该IP地址处于同一个网段上的客户程序才能与该服务程序通信。我们用0来填充sin_zero数组,目的是让sockaddr_in结构的大小与sockaddr结构的大小一致。下面是一个bind函数调用的例子:
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr));
八、listen函数
int listen( SOCKET s, int backlog );
服务程序可以调用listen函数使其流套接字s处于监听状态。处于监听状态的流套接字s将维护一个客户连接请求队列,该队列最多容纳backlog个客户连接请求。假如该函数执行成功,则返回0;如果执行失败,则返回SOCKET_ERROR。
九、accept函数
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
服务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结构的长度。下面是一个调用accept的例子:
struct sockaddr_in ServerSocketAddr;
int addrlen;
addrlen=sizeof(ServerSocketAddr);
ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);
十、connect函数
int connect(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
客户程序调用connect函数来使客户Socket s与监听于name所指定的计算机的特定端口上的服务Socket进行连接。如果连接成功,connect返回0;如果失败则返回SOCKET_ERROR。下面是一个例子:
struct sockaddr_in daddr;
memset((void *)&daddr,0,sizeof(daddr));
daddr.sin_family=AF_INET;
daddr.sin_port=htons(8888);
daddr.sin_addr.s_addr=inet_addr("133.197.22.4");
connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr));
29.线程和进程:
  [前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力。用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义。现在的应用软件无一不是多线程多任务处理,单线城的软件是不可想象的。因此掌握多线程多任务设计方法对每个程序员都是必需要掌握的。本文针对多线程技术在应用中经常遇到的问题,如线程间的通信、同步等,对它们分别进行探讨。
  一、 理解线程
  要讲解线程,不得不说一下进程,进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它系统资源组成。进程在运行时创建的资源随着进程的终止而死亡。线程的基本思想很简单,它是一个独立的执行流,是进程内部的一个独立的执行单元,相当于一个子程序,它对应Visual C++中的CwinThread类的对象。单独一个执行程序运行时,缺省的运行包含的一个主线程,主线程以函数地址的形式,如main或WinMain函数,提供程序的启动点,当主线程终止时,进程也随之终止,但根据需要,应用程序又可以分解成许多独立执行的线程,每个线程并行的运行在同一进程中。
  一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行,由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU的时间,优先级高的线程优先运行,优先级低的线程则继续等待。
  线程被分为两种:用户界面线程和工作线程(又称为后台线程)。用户界面线程通常用来处理用户的输入并响应各种事件和消息,其实,应用程序的主执行线程CWinAPP对象就是一个用户界面线程,当应用程序启动时自动创建和启动,同样它的终止也意味着该程序的结束,进城终止。工作者线程用来执行程序的后台处理任务,比如计算、调度、对串口的读写操作等,它和用户界面线程的区别是它不用从CwinThread类派生来创建,对它来说最重要的是如何实现工作线程任务的运行控制函数。工作线程和用户界面线程启动时要调用同一个函数的不同版本;最后需要读者明白的是,一个进程中的所有线程共享它们父进程的变量,但同时每个线程可以拥有自己的变量。
  二、 线程的管理和操作
  1. 线程的启动
  创建一个用户界面线程,首先要从类CwinThread产生一个派生类,同时必须使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE来声明和实现这个CwinThread派生类。
  第二步是根据需要重载该派生类的一些成员函数如:ExitInstance();InitInstance();OnIdle();PreTranslateMessage()等函数,最后启动该用户界面线程,调用AfxBeginThread()函数的一个版本:CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );其中第一个参数为指向定义的用户界面线程类指针变量,第二个参数为线程的优先级,第三个参数为线程所对应的堆栈大小,第四个参数为线程创建时的附加标志,缺省为正常状态,如为CREATE_SUSPENDED则线程启动后为挂起状态。
  对于工作线程来说,启动一个线程,首先需要编写一个希望与应用程序的其余部分并行运行的函数如Fun1(),接着定义一个指向CwinThread对象的指针变量*pThread,调用AfxBeginThread(Fun1,param,priority)函数,返回值付给pThread变量的同时一并启动该线程来执行上面的Fun1()函数,其中Fun1是线程要运行的函数的名字,也既是上面所说的控制函数的名字,param是准备传送给线程函数Fun1的任意32位值,priority则是定义该线程的优先级别,它是预定义的常数,读者可参考MSDN。
  2.线程的优先级
  以下的CwinThread类的成员函数用于线程优先级的操作:
int GetThreadPriority();
BOOL SetThradPriority()(int nPriority);
上述的二个函数分别用来获取和设置线程的优先级,这里的优先级,是相对于该线程所处的优先权层次而言的,处于同一优先权层次的线程,优先级高的线程先运行;处于不同优先权层次上的线程,谁的优先权层次高,谁先运行。至于优先级设置所需的常数,自己参考MSDN就可以了,要注意的是要想设置线程的优先级,这个线程在创建时必须具有THREAD_SET_INFORMATION访问权限。对于线程的优先权层次的设置,CwinThread类没有提供相应的函数,但是可以通过Win32 SDK函数GetPriorityClass()和SetPriorityClass()来实现。
  3.线程的悬挂、恢复
  CwinThread类中包含了应用程序悬挂和恢复它所创建的线程的函数,其中SuspendThread()用来悬挂线程,暂停线程的执行;ResumeThread()用来恢复线程的执行。如果你对一个线程连续若干次执行SuspendThread(),则需要连续执行相应次的ResumeThread()来恢复线程的运行。
  4.结束线程
  终止线程有三种途径,线程可以在自身内部调用AfxEndThread()来终止自身的运行;可以在线程的外部调用BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode )来强行终止一个线程的运行,然后调用CloseHandle()函数释放线程所占用的堆栈;第三种方法是改变全局变量,使线程的执行函数返回,则该线程终止。下面以第三种方法为例,给出部分代码:
////////////////////////////////////////////////////////////////
//////CtestView message handlers
/////Set to True to end thread
Bool bend=FALSE;//定义的全局变量,用于控制线程的运行
//The Thread Function
UINT ThreadFunction(LPVOID pParam)//线程函数
{
while(!bend)
{Beep(100,100);
Sleep(1000);
}
return 0;
}
CwinThread *pThread;
HWND hWnd;
/////////////////////////////////////////////////////////////
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
pThread=AfxBeginThread(ThradFunction,hWnd);//启动线程
pThread->m_bAutoDelete=FALSE;//线程为手动删除
Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{ bend=TRUE;//改变变量,线程结束
WaitForSingleObject(pThread->m_hThread,INFINITE);//等待线程结束
delete pThread;//删除线程
Cview::OnDestroy();
}
  三、 线程之间的通信
  通常情况下,一个次级线程要为主线程完成某种特定类型的任务,这就隐含着表示在主线程和次级线程之间需要建立一个通信的通道。一般情况下,有下面的几种方法实现这种通信任务:使用全局变量(上一节的例子其实使用的就是这种方法)、使用事件对象、使用消息。这里我们主要介绍后两种方法。
  1. 利用用户定义的消息通信
  在Windows程序设计中,应用程序的每一个线程都拥有自己的消息队列,甚至工作线程也不例外,这样一来,就使得线程之间利用消息来传递信息就变的非常简单。首先用户要定义一个用户消息,如下所示:#define WM_USERMSG WMUSER+100;在需要的时候,在一个线程中调用
::PostMessage((HWND)param,WM_USERMSG,0,0)

CwinThread::PostThradMessage()
来向另外一个线程发送这个消息,上述函数的四个参数分别是消息将要发送到的目的窗口的句柄、要发送的消息标志符、消息的参数WPARAM和LPARAM。下面的代码是对上节代码的修改,修改后的结果是在线程结束时显示一个对话框,提示线程结束:
UINT ThreadFunction(LPVOID pParam)
{
while(!bend)
{
Beep(100,100);
Sleep(1000);
}
::PostMessage(hWnd,WM_USERMSG,0,0);
return 0;
}
////////WM_USERMSG消息的响应函数为OnThreadended(WPARAM wParam,LPARAM lParam)
LONG CTestView::OnThreadended(WPARAM wParam,LPARAM lParam)
{
AfxMessageBox("Thread ended.");
Retrun 0;
}
上面的例子是工作者线程向用户界面线程发送消息,对于工作者线程,如果它的设计模式也是消息驱动的,那么调用者可以向它发送初始化、退出、执行某种特定的处理等消息,让它在后台完成。在控制函数中可以直接使用::GetMessage()这个SDK函数进行消息分检和处理,自己实现一个消息循环。GetMessage()函数在判断该线程的消息队列为空时,线程将系统分配给它的时间片让给其它线程,不无效的占用CPU的时间,如果消息队列不为空,就获取这个消息,判断这个消息的内容并进行相应的处理。
  2.用事件对象实现通信
  在线程之间传递信号进行通信比较复杂的方法是使用事件对象,用MFC的Cevent类的对象来表示。事件对象处于两种状态之一:有信号和无信号,线程可以监视处于有信号状态的事件,以便在适当的时候执行对事件的操作。上述例子代码修改如下:
////////////////////////////////////////////////////////////////////
Cevent threadStart,threadEnd;
////////////////////////////////////////////////////////////////////
UINT ThreadFunction(LPVOID pParam)
{
::WaitForSingleObject(threadStart.m_hObject,INFINITE);
AfxMessageBox("Thread start.");
while(!bend)
{
Beep(100,100);
Sleep(1000);
Int result=::WaitforSingleObject(threadEnd.m_hObject,0);
//等待threadEnd事件有信号,无信号时线程在这里悬停
If(result==Wait_OBJECT_0)
Bend=TRUE;
}
::PostMessage(hWnd,WM_USERMSG,0,0);
return 0;
}
/////////////////////////////////////////////////////////////
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
threadStart.SetEvent();//threadStart事件有信号
pThread=AfxBeginThread(ThreadFunction,hWnd);//启动线程
pThread->m_bAutoDelete=FALSE;
Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{ threadEnd.SetEvent();
WaitForSingleObject(pThread->m_hThread,INFINITE);
delete pThread;
Cview::OnDestroy();
}
运行这个程序,当关闭程序时,才显示提示框,显示"Thread ended"
  四、 线程之间的同步
  前面我们讲过,各个线程可以访问进程中的公共变量,所以使用多线程的过程中需要注意的问题是如何防止两个或两个以上的线程同时访问同一个数据,以免破坏数据的完整性。保证各个线程可以在一起适当的协调工作称为线程之间的同步。前面一节介绍的事件对象实际上就是一种同步形式。Visual C++中使用同步类来解决操作系统的并行性而引起的数据不安全的问题,MFC支持的七个多线程的同步类可以分成两大类:同步对象(CsyncObject、Csemaphore、Cmutex、CcriticalSection和Cevent)和同步访问对象(CmultiLock和CsingleLock)。本节主要介绍临界区(critical section)、互斥(mutexe)、信号量(semaphore),这些同步对象使各个线程协调工作,程序运行起来更安全。
  1. 临界区
  临界区是保证在某一个时间只有一个线程可以访问数据的方法。使用它的过程中,需要给各个线程提供一个共享的临界区对象,无论哪个线程占有临界区对象,都可以访问受到保护的数据,这时候其它的线程需要等待,直到该线程释放临界区对象为止,临界区被释放后,另外的线程可以强占这个临界区,以便访问共享的数据。临界区对应着一个CcriticalSection对象,当线程需要访问保护数据时,调用临界区对象的Lock()成员函数;当对保护数据的操作完成之后,调用临界区对象的Unlock()成员函数释放对临界区对象的拥有权,以使另一个线程可以夺取临界区对象并访问受保护的数据。同时启动两个线程,它们对应的函数分别为WriteThread()和ReadThread(),用以对公共数组组array[]操作,下面的代码说明了如何使用临界区对象:
#include "afxmt.h"
int array[10],destarray[10];
CCriticalSection Section;
////////////////////////////////////////////////////////////////////////
UINT WriteThread(LPVOID param)
{Section.Lock();
for(int x=0;x<10;x++)
array[x]=x;
Section.Unlock();
}
UINT ReadThread(LPVOID param)
{
Section.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
Section.Unlock();
}
上述代码运行的结果应该是Destarray数组中的元素分别为1-9,而不是杂乱无章的数,如果不使用同步,则不是这个结果,有兴趣的读者可以实验一下。
  2. 互斥
  互斥与临界区很相似,但是使用时相对复杂一些,它不仅可以在同一应用程序的线程间实现同步,还可以在不同的进程间实现同步,从而实现资源的安全共享。互斥与Cmutex类的对象相对应,使用互斥对象时,必须创建一个CSingleLock或CMultiLock对象,用于实际的访问控制,因为这里的例子只处理单个互斥,所以我们可以使用CSingleLock对象,该对象的Lock()函数用于占有互斥,Unlock()用于释放互斥。实现代码如下:
#include "afxmt.h"
int array[10],destarray[10];
CMutex Section;
/////////////////////////////////////////////////////////////
UINT WriteThread(LPVOID param)
{ CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
for(int x=0;x<10;x++)
array[x]=x;
singlelock.Unlock();
}
UINT ReadThread(LPVOID param)
{ CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
singlelock.Unlock();
}
  3. 信号量
  信号量的用法和互斥的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源,创建一个信号量需要用Csemaphore类声明一个对象,一旦创建了一个信号量对象,就可以用它来对资源的访问技术。要实现计数处理,先创建一个CsingleLock或CmltiLock对象,然后用该对象的Lock()函数减少这个信号量的计数值,Unlock()反之。下面的代码分别启动三个线程,执行时同时显示二个消息框,然后10秒后第三个消息框才得以显示。
/////////////////////////////////////////////////////////////////
Csemaphore *semaphore;
Semaphore=new Csemaphore(2,2);
HWND hWnd=GetSafeHwnd();
AfxBeginThread(threadProc1,hWnd);
AfxBeginThread(threadProc2,hWnd);
AfxBeginThread(threadProc3,hWnd);
//////////////////////////////////////////////////////////////////////
UINT ThreadProc1(LPVOID param)
{CsingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread1 had access","Thread1",MB_OK);
return 0;
}
UINT ThreadProc2(LPVOID param)
{CSingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread2 had access","Thread2",MB_OK);
return 0;
}
UINT ThreadProc3(LPVOID param)
{CsingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread3 had access","Thread3",MB_OK);
return 0;
30.程序的自动运行:
内容提要
  在工作中经常遇到一些程序,当计算机启动时会自动将该程序加载,以实现对计算机的监控等特殊的目的。本文就针对这个问题,阐述了系统加载特定程序的原理和方法,同时利用VC++ 6.0编程实现这种特定的功能的,并对其中的关键代码进行了分析。
文章正文
  工作中经常遇到一些程序,它们在系统启动的过程中,自动打开并运行,以便实现对系统的监控或者病毒的检测等特定的目的,典型的例子就是常用的一些杀毒软件如:KV300及瑞星杀毒软件等。笔者在此,以自己的编程实践为基础,说明这些这些程序自动启动的原理和方法,同时对一些典型程序代码进行分析,以便读者在今后的编程过程中使用。
一、 程序自动启动的原理及方法:
1. 利用WIN.INI文件实现相关程序的自动启动
  WIN.INI是系统保存在C:WINDOWS目录下的一个系统初始化文件。系统在起动时会检索该文件中的相关项,以便对系统环境的初始设置。
  在该文件中的"[windows]"数据段中,有两个数据项"load="和"run=",它们的作用就是在系统起动之后自动得装入和运行相关的程序。如果我们需要在系统起动之后装入并运行一个程序,只将需要运行文件的全文件名添加在该数据项的后面系统起动后就会自动运行该程序,系统也会进入特定的操作环境中去。
2. 利用注册表实现相关程序的自动启动
  系统注册表保存着系统的软件、硬件及其他与系统配置有关的重要信息,一个计算机系统的系统注册表一旦遭到破坏,整个系统将无法运行。
  在计算机的系统注册表中的子目录中有一个目录的名称为HKEY_LOCAL_MACHINESoftware MicrosoftWindowsCurrent_VersionRun,如果你想让程序在系统起动的过程中启动该程序,就可以向该目录添加一个子项,具体的过程是在注册表中右击该项,选中其中的"新建"项目,然后选中其中的"串值",建立新的串值后将它的名称改成相应的名称,双击新建的串值,输入新的数值,自动启动程序的过程就设置完成。
9月1日

学习心得:不要被原有思维所束缚

 

    昨天在调整portal的功能时,解决了一个之前一直认为无法解决的问题,就是如何在不同的页面中个性化左侧的ipanel,比如在a页面中要求是隐藏的,而在b页面中要求是open的,最终的解决很简单的,只是在页面的属性当中设置一下就可以了。
查看更多精彩图片

    但是回过头来想一想,为什么这么简单的问题我一直没有解决掉,找不到解决办法呢,我之前的注意力全部集中在整个frameset的属性上了,我一直认为只有frameset才能控制个个area的显示,而页面是在content area区域显示的,根本就不会想到在content area中可以控制到相邻的ipanel。

     有了这样的一个先入为主的观念,我就再没有脱离开这个框架想问题,也就导致了直到系统正式上线才得以解决这个问题。

      其实不止在这一个地方,在好多时候遇到好多问题,都会掉入这样一个先入为主的陷阱,然后在自己给自己划定的圈圈里转,始终不肯跳出这个圈圈想问题。

      所以从这个问题上得到的教训就是当遇到难题无法解决时,不妨换个角度重新思考,甚至是推翻原先所有的认识,从头再认识,也许问题就会迎刃而解了。

 

8月23日

我的世界只有黑与白

    一直在努力改正自己,一直在修炼自己的涵养,可是到头来,发现还是在原地踏步,还是以前那个脾气暴躁,不懂包容的人。

    早上,发现项目里的服务器又出现了以前同样的故障,发现又是同一个人做了同样的事情引发的同样的后果,当时真的是想都没想,立刻爆发了出来。

    我真的不想这样,我也想象高手那样,羽扇纶巾,谈笑间,强掳灰飞烟灭。可惜我不是,我就是一个不懂交际,不懂世故的小程序员,所以我做了我最习惯做的,和同事吵了一架。

    发泄完,挺后悔的,为了项目的事情和别人吵架,又伤神又伤感情,还没有利益可图,真是太划不来。老大是这样教导我的“我们要善于观察别人的性格,调整对不同性格人的交流沟通方式,凡事先从别人的角度出发思考问题,学会原谅别人,如果真的遇到自己觉得生气的事情,你可以提醒自己先忍耐十分钟,之后再决定是否有必要去发怒”。难道真的是我大脑太简单了,只会走直线,不会走曲线?

    我始终认为,做错事情,最起码的责任是承认,而不是狡辩。

    中国人最擅长的就是中庸之道,不说黑,不说白,而是黑白之间,毕竟大家都喜欢看彩色电视机而不是黑白的。我不知道什么时候能学会老祖宗遗留下来的中庸之道。

    也许我根本就学不来,也许是得自遗传,也许是我的世界只有黑与白。 

7月2日

再赏《荷塘月色》

    今天解决了trex在portal中的使用问题,心情真的很舒畅,找出高中时期很欣赏的一篇文章《荷塘月色》来品味,希望也能给网友们带来一些放松的感觉。
    沿着荷塘,是一条曲折的小煤屑路。这是一条 幽僻的路;白天也少人走,夜晚更加寂寞。荷塘四面,长着许多树,蓊蓊郁郁的。路的一旁 ,是些杨柳,和一些不知道名字的树。没有月光的晚上,这路上阴森森的,有些怕人。今晚却很好,虽然月光也还是淡淡的。
    路上只我一人,背着手踱着。这一片天地好象是我的;我也象超出了平常的自己,到了另一个世界里。我爱热闹,也爱冷静;爱群居,也爱独处。象今晚上,一个人在这苍茫的月下, 什么都可以想,什么都可以不想,便觉是个自由的人。白天里一定要做的事,一定要说的话 ,现在都可以不理。这是独处的妙处;我且受用这无边的荷香月色好了。
     。叶子出水很高,象亭亭的舞女的裙。层层的叶 子中间,零星地点缀着些白花,有袅娜地开着的,有羞涩地打着朵的;正如一粒粒的明珠, 又如天里的星星。微风过处,送来缕缕清香, 仿佛远处高楼上渺茫的歌声似的。这时候叶子 与花也有一丝的颤动,象闪电般,霎时传过荷 塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有一了道凝碧的波痕。叶子底下是脉 脉的流水,遮住了,不能见一些颜色;而叶子却更见风致了。
    月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又象笼着轻纱的梦。虽然是满月,天上却有一层淡淡的云,所以不能朗照;但我以为这恰是到了好处--酣眠固不可少,小睡也是别有风味的。月光是隔了树照过来的,高处丛生的灌木,落下参差的斑驳的黑影;弯弯的杨柳的稀疏的倩影,象是画在荷叶上。塘中的月色并不均匀;但光与影有着和谐的旋律,如梵婀玲上奏着的名曲。
    月色是美的,荷塘更美,但最给我感觉的确实“曲曲折折的荷塘上面,弥望的是田田的叶子”,每读到这里,总是能给我最美的意境,使我远离这个污七八糟的世界,到了另一个世界,思想无边无界的蔓延开去,尽情的驰骋着。似迷似雾,似痴似醉,真的到了仙境一般。如果有那么一天,牵手佳人,共临此境,真的是人生幸事了。
6月19日

谈论 java面试常见题目与答案

 

引用

java面试常见题目与答案

Java基础方面:

 

 


1、作用域public,private,protected,以及不写时的区别
答:区别如下:
作用域           当前类       同一package  子孙类       其他package
public            √              √                  √             √
protected        √              √                  √             ×
friendly          √              √                   ×            ×
private           √              ×                   ×            ×
不写时默认为friendly
2、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)
答:匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现
3、Static Nested Class 和 Inner Class的不同
答:Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象
4、&和&&的区别
答:&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)
5、Collection 和 Collections的区别
答:Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
6、什么时候用assert
答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,系统将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的
7、String s = new String("xyz");创建了几个String Object
答:两个,一个字符对象,一个字符对象引用对象
8、Math.round(11.5)等於多少? Math.round(-11.5)等於多少
答:  Math.round(11.5)==12;Math.round(-11.5)==-11;round方法返回与参数最接近的长整数,参数加1/2后求其floor
9、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错
答:short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)short s1 = 1; s1 += 1;(可以正确编译)
10、Java有没有goto
答:java中的保留字,现在没有在java中使用
11、数组有没有length()这个方法? String有没有length()这个方法
答:数组没有length()这个方法,有length的属性。String有有length()这个方法
12、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型
答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型
13、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别
答:Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等
    equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值
14、给我一个你最常见到的runtime exception
答:常见的运行时异常有如下这些ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
15、error和exception有什么区别
答:error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况
    exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况
16、List, Set, Map是否继承自Collection接口
答: List,Set是,Map不是
17、abstract class和interface有什么区别
答:声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法
接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口
18、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized
答:都不能

 

 

 

19、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数
20、构造器Constructor是否可被override
答:构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading
21、是否可以继承String类
答:String类是final类故不可以继承
22、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后
答:会执行,在return前执行
23、用最有效率的方法算出2乘以8等於几
答:2 << 3
24、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对
答:不对,有相同的hash code
25、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递
答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的
26、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
答:witch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich
27、ArrayList和Vector的区别,HashMap和Hashtable的区别
答:就ArrayList与Vector主要从二方面来说.
一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半
就HashMap与HashTable主要从三方面来说。
一.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现
二.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的
三.值:只有HashMap可以让你将空值作为一个表的条目的key或value

 

 

 

28、char型变量中能不能存贮一个中文汉字?为什么?
答:是能够定义成为一个中文的,因为java中以unicode编码,一个char占16个字节,所以放一个中文是没问题的
29、GC是什么? 为什么要有GC
答:GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
30、float型float f=3.4是否正确?
答:不正确。精度不准确,应该用强制类型转换,如下所示:float f=(float)3.4
31、介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)?
答:Collection FrameWork如下:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)
Map提供key到value的映射
32、抽象类与接口?
答:抽象类与接口都用于抽象,但是抽象类(JAVA中)可以有自己的部分实现,而接口则完全是一个标识(同时有多重继承的功能)。
JAVA类实现序例化的方法是实现java.io.Serializable接口
Collection框架中实现比较要实现Comparable 接口和 Comparator 接口
33、STRING与STRINGBUFFER的区别。
答:STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法
34、谈谈final, finally, finalize的区别
答:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的
35、面向对象的特征有哪些方面
答:主要有以下四方面:
1.抽象:
抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
2.继承:
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
3.封装:
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
4. 多态性:
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
36、String是最基本的数据类型吗
答:基本数据类型包括byte、int、char、long、float、double、boolean和short。
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类
37、int 和 Integer 有什么区别
答:Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。
原始类型封装类,booleanBoolean,charCharacter,byteByte,shortShort,intInteger,longLong,floatFloat,doubleDouble
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关
38、运行时异常与一般异常有何异同
答:异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
39、说出ArrayList,Vector, LinkedList的存储性能和特性
答:ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
40、HashMap和Hashtable的区别
答:HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
41、heap和stack有什么区别
答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素
42、Java的接口和C++的虚类的相同和不同处
答:由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。
43、Java中的异常处理机制的简单原理和应用
答:当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。
43、垃圾回收的优点和原理。并考虑2种回收机制
答:Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
44、你所知道的集合类都有哪些?主要方法?
答:最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。
Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。
45、描述一下JVM加载class文件的原理机制?
答:JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。
46、排序都有哪几种方法?请列举
答:  排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序),选择排序(直接选择排序、堆排序),归并排序,分配排序(箱排序、基数排序)
快速排序的伪代码。
/ /使用快速排序方法对a[ 0 :n- 1 ]排序
从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e,该元素为支点
把余下的元素分割为两段left 和r i g h t,使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点
递归地使用快速排序方法对left 进行排序
递归地使用快速排序方法对right 进行排序
所得结果为l e f t + m i d d l e + r i g h t
47、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
答:Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。
用try来指定一块预防所有"异常"的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的"异常"的类型。
throw语句用来明确地抛出一个"异常"。
throws用来标明一个成员函数可能抛出的各种"异常"。
Finally为确保一段代码不管发生什么"异常"都被执行一段代码。
可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常"的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到有处理这种"异常"的try语句。
48、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
答:可以。必须只有一个类名与文件名相同。
49、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
答:字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReader OutputStreamWriter。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。
50、java中会存在内存泄漏吗,请简单描述。
答:会。自己实现堆载的数据结构时有可能会出现内存泄露,可参看effective java.
51、java中实现多态的机制是什么?
答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
52、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收
答:对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
53、静态变量和实例变量的区别?
答:static i = 10; //常量   class A a;  a.i =10;//可变
54、什么是java序列化,如何实现java序列化?
答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
55、是否可以从一个static方法内部发出对非static方法的调用?
答:不可以,如果其中包含对象的method();不能保证对象初始化.
56、写clone()方法时,通常都有一行代码,是什么?
答:Clone 有缺省行为,super.clone();他负责产生正确大小的空间,并逐位复制。
57、在JAVA中,如何跳出当前的多重嵌套循环?
答:用break; return 方法。
58、List、Map、Set三个接口,存取元素时,各有什么特点?
答:List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值,value可多值。
59、说出一些常用的类,包,接口,请各举5个
答:常用的类:BufferedReader  BufferedWriter  FileReader  FileWirter  String  Integer
常用的包:java.lang  java.awt  java.io  java.util  java.sql
常用的接口:Remote  List  Map  Document  NodeList

谈论 应聘Java笔试时可能出现问题及其答案(第二版 第二部分)

 

引用

应聘Java笔试时可能出现问题及其答案(第二版 第二部分)
应聘Java笔试时可能出现问题及其答案(第二版 第二部分)
线程编程方面   
 
 
 
60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
答:有两种实现方法,分别是继承Thread类与实现Runnable接口
用synchronized关键字修饰同步方法
反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。
61、sleep() 和 wait() 有什么区别?
答:sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
62、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
答:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
63、启动一个线程是用run()还是start()?
答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
64、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
答:不能,一个对象的一个synchronized方法只能由一个线程访问。
65、请说出你所知道的线程同步的方法。
答:wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
66、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?
答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口
同步的实现方面有两种,分别是synchronized,wait与notify
67、线程的基本概念、线程的基本状态以及状态之间的关系
答:线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。
Java中的线程有四种状态分别是:运行、就绪、挂起、结束
68、简述synchronized和java.util.concurrent.locks.Lock的异同 ?
答:主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。
 
 
 
Jsp方面
 
 
 
69、forward 和redirect的区别
答:forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
    redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
70、jsp有哪些内置对象?作用分别是什么?
答:JSP共有以下9种基本内置组件(可与ASP的6种内部组件相对应):
 request 用户端请求,此请求会包含来自GET/POST请求的参数
   response 网页传回用户端的回应
   pageContext 网页的属性是在这里管理
   session 与请求有关的会话期
   application servlet 正在执行的内容
   out 用来传送回应的输出
   config servlet的构架部件
   page JSP网页本身
   exception 针对错误网页,未捕捉的例外
71、jsp有哪些动作?作用分别是什么?
答:JSP共有以下6种基本动作
   jsp:include:在页面被请求的时候引入一个文件。
   jsp:useBean:寻找或者实例化一个JavaBean。
   jsp:setProperty:设置JavaBean的属性。
   jsp:getProperty:输出某个JavaBean的属性。
   jsp:forward:把请求转到一个新的页面。
   jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记
72、JSP中动态INCLUDE与静态INCLUDE的区别?
答:动态INCLUDE用jsp:include动作实现
   <jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数
   静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面
   <%@ include file="included.htm" %>
73、两种跳转方式分别是什么?有什么区别?
答:有两种,分别为:
  <jsp:include page="included.jsp" flush="true">
  <jsp:forward page= "nextpage.jsp"/>
前者页面不会转向include所指的页面,只是显示该页的结果,主页面还是原来的页面。执行完后还会回来,相当于函数调用。并且可以带参数.后者完全转向新页面,不会再回来。相当于go to 语句。
74、JSP的内置对象及方法。
答:request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。
    response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等)
    out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。
    pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。
    session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息
    applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息
    config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。
    page表示从该页面产生的一个servlet实例
 
 
 
Servlet方面
 
 
 
75、说一说Servlet的生命周期?
答:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
76、JAVA SERVLET API中forward() 与redirect()的区别?
答:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。
77、Servlet的基本架构
答:
public class ServletName extends HttpServlet {
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws
      ServletException, IOException  {
      }
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws
      ServletException, IOException  {
      }
}
 
 
 
78、什么情况下调用doGet()和doPost()?
答:Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()。
79、servlet的生命周期
答:web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servlet的destroy()方法。
80、如何现实servlet的单线程模式
答:<%@ page isThreadSafe="false"%>
81、页面间对象传递的方法
答:request,session,application,cookie等
82、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
答:JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
83、四种会话跟踪技术
答:会话作用域ServletsJSP 页面描述
page否是代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示。这既包括 servlet 又包括被编译成 servlet 的 JSP 页面
request是是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系)
session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求
application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域
84、Request对象的主要方法
答:
setAttribute(String name,Object):设置名字为name的request的参数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例
getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组
getCharacterEncoding():返回请求中的字符编码方式
getContentLength():返回请求的Body的长度
getHeader(String name):获得HTTP协议定义的文件头信息
getHeaders(String name):返回指定名字的request Header的所有值,结果是一个枚举的实例
getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例
getInputStream():返回请求的输入流,用于获得请求中的数据
getMethod():获得客户端向服务器端传送数据的方法
getParameter(String name):获得客户端传送给服务器端的有name指定的参数值
getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例
getParameterValues(String name):获得有name指定的参数的所有值
getProtocol():获取客户端向服务器端传送数据所依据的协议名称
getQueryString():获得查询字符串
getRequestURI():获取发出请求字符串的客户端地址
getRemoteAddr():获取客户端的IP地址
getRemoteHost():获取客户端的名字
getSession([Boolean create]):返回和请求相关Session
getServerName():获取服务器的名字
getServletPath():获取客户端所请求的脚本文件的路径
getServerPort():获取服务器的端口号
removeAttribute(String name):删除请求中的一个属性
85、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
答:
  Public String translate (String str) {
    String tempStr = "";
    try {
      tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
      tempStr = tempStr.trim();
    }
    catch (Exception e) {
      System.err.println(e.getMessage());
    }
    return tempStr;
  }
86、Servlet执行时一般实现哪几个方法?
答:
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()
 
 
 
Jdbc、Jdo方面
 
 
 
87、Class.forName的作用?为什么要用?
答:调用该访问返回一个以字符串指定类名的类的对象。
88、Jdo是什么?
答:JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。
89、说出数据连接池的工作机制是什么?
答:J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。
90、Jdo是什么?
答:JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。
Xml方面
 
 
 
91、xml有哪些解析技术?区别是什么?
答:有DOM,SAX,STAX等
DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问
STAX:Streaming API for XML (StAX)
92、你在项目中用到了xml技术的哪些方面?如何实现的?
答:用到了数据存贮,信息配置两方面。在做数据交换平台时,将不能数据源的数据组装成XML文件,然后将XML文件压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时,利用XML可以很方便的进行,软件的各种配置参数都存贮在XML文件中。
93、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
答:a: 两种形式 dtd  schema,b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的),c:有DOM,SAX,STAX等
    DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问
SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问
STAX:Streaming API for XML (StAX)
 

谈论 应聘Java笔试时可能出现问题及其答案(第二版 第三部分)

 

引用

应聘Java笔试时可能出现问题及其答案(第二版 第三部分)
应聘Java笔试时可能出现问题及其答案(第二版 第三部分)
EJB方面
 
 
94、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别?
答:规范内容包括Bean提供者,应用程序装配者,EJB容器,EJB配置工具,EJB服务提供者,系统管理员。这里面,EJB容器是EJB之所以能够运行的核心。EJB容器管理着EJB的创建,撤消,激活,去活,与数据库的连接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC,JMS.....
95、EJB与JAVA BEAN的区别?
答:Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。
96、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。
 答:EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。
SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。
对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。
对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。
Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时,会是同一个 Bean 的 Instance 在执行。从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。
97、EJB与JAVA BEAN的区别?
答:Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?
SessionBean:Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例。
EntityBean:Entity Beans能存活相对较长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。
EJB通过以下技术管理实务:对象管理组织(OMG)的对象实务服务(OTS),Sun Microsystems的Transaction Service(JTS)、Java Transaction API(JTA),开发组(X/Open)的XA接口。
98、EJB的角色和三个对象
答:一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(Enterprise Bean Provider) 、应用组合者(Application Assembler)、部署者(Deployer)、EJB 服务器提供者(EJB Server Provider)、EJB 容器提供者(EJB Container Provider)、系统管理员(System Administrator)
三个对象是Remote(Local)接口、Home(LocalHome)接口,Bean类
99、EJB容器提供的服务
答:主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。
100、EJB规范规定EJB中禁止的操作有哪些?
 答:1.不能操作线程和线程API(线程API指非线程对象的方法如notify,wait等),2.不能操作awt,3.不能实现服务器功能,4.不能对静态属生存取,5.不能使用IO操作直接存取文件系统,6.不能加载本地库.,7.不能将this作为变量和返回,8.不能循环调用。
101、remote接口和home接口主要作用
答:remote接口定义了业务方法,用于EJB客户端调用业务方法。
home接口是EJB工厂用于创建和移除查找EJB实例
102、bean 实例的生命周期
答:对于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在缓冲池管理,而对于Entity Bean和Statefull Session Bean存在Cache管理,通常包含创建实例,设置上下文、创建EJB Object(create)、业务方法调用、remove等过程,对于存在缓冲池管理的Bean,在create之后实例并不从内存清除,而是采用缓冲池调度机制不断重用实例,而对于存在Cache管理的Bean则通过激活和去激活机制保持Bean的状态并限制内存中实例数量。
103、EJB的激活机制
答:以Stateful Session Bean 为例:其Cache大小决定了内存中可以同时存在的Bean实例的数量,根据MRU或NRU算法,实例在激活和去激活状态之间迁移,激活机制是当客户端调用某个EJB实例业务方法时,如果对应EJB Object发现自己没有绑定对应的Bean实例则从其去激活Bean存储中(通过序列化机制存储实例)回复(激活)此实例。状态变迁前会调用对应的ejbActive和ejbPassivate方法。
104、EJB的几种类型
答:会话(Session)Bean ,实体(Entity)Bean 消息驱动的(Message Driven)Bean
会话Bean又可分为有状态(Stateful)和无状态(Stateless)两种
实体Bean可分为Bean管理的持续性(BMP)和容器管理的持续性(CMP)两种
105、客服端调用EJB对象的几个基本步骤
答:设置JNDI服务工厂以及JNDI服务地址系统属性,查找Home接口,从Home接口调用Create方法创建Remote接口,通过Remote接口调用其业务方法。
 
 
 
应用服务器方面
 
 
 
106、如何给weblogic指定大小的内存?
答:在启动Weblogic的脚本中(位于所在Domian对应服务器目录下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以调整最小内存为32M,最大200M
EJB需直接实现它的业务接口或Home接口吗,请简述理由。
远程接口和Home接口不需要直接实现,他们的实现代码是由服务器产生的,程序运行中对应实现类会作为对应接口类型的实例被使用。
107、应用服务器有那些?
答:BEA WebLogic Server,IBM WebSphere Application Server,Oracle9i Application Server,jBoss,Tomcat
108、如何设定的weblogic的热启动模式(开发模式)与产品发布模式?
答:可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件,增加set PRODUCTION_MODE=true。
109、如何启动时不需输入用户名与密码?
答:修改服务启动文件,增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.
110、在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中?
答:保存在此Domain的config.xml文件中,它是服务器的核心配置文件。
111、说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入 http://主机:端口号//helloword.jsp就可以看到运行结果了?  又比如这其中用到了一个自己写的javaBean该如何办?
答:Domain目录服务器目录applications,将应用目录放在此目录下将可以作为应用访问,如果是Web应用,应用目录需要满足Web应用目录要求,jsp文件可以直接放在应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,设置服务器的缺省应用将可以实现在浏览器上无需输入应用名。
112、在weblogic中发布ejb需涉及到哪些配置文件
答:不同类型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml
86、如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置
缺省安装中使用DemoIdentity.jks和DemoTrust.jks  KeyStore实现SSL,需要配置服务器使用Enable SSL,配置其端口,在产品模式下需要从CA获取私有密钥和数字证书,创建identity和trust keystore,装载获得的密钥和数字证书。可以配置此SSL连接是单向还是双向的。
113、如何查看在weblogic中已经发布的EJB?
答:可以使用管理控制台,在它的Deployment中可以查看所有已发布的EJB
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过来,而non-persistent方式的消息将被丢弃。
 
 
 
J2EE,MVC方面
 
 
 
114、MVC的各个部分都有那些技术来实现?如何实现?
答:MVC是Model-View-Controller的简写。"Model" 代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表示面(由JSP页面产生),"Controller" 是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。
115、J2EE是什么?
答:Je22是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中,可按照功能划分为不同的组件,这些组件又可在不同计算机上,并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。
116、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。
答:Web Service描述语言WSDL
SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。
UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
117、J2EE是技术还是平台还是框架?
答:J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。
 J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。
118、STRUTS的应用(如STRUTS架构)
答:Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能:
一.包含一个controller servlet,能将用户的请求发送到相应的Action对象。
二.JSP自由tag库,并且在controller servlet中提供关联支持,帮助开发员创建交互式表单应用。
三.提供了一系列实用对象:XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。
119、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。
答:Web ServiceWeb Service是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼容的组件进行互操作。
JAXP(Java API for XML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口,当你需要改变具体的实现时候也不需要修改代码。
JAXM(Java API for XML Messaging) 是为SOAP通信提供访问方法和传输机制的API。
WSDL是一种 XML 格式,用于将网络服务描述为一组端点,这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述,然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点(服务)。
SOAP即简单对象访问协议(Simple Object Access Protocol),它是用于交换XML编码信息的轻量级协议。
UDDI 的目的是为电子商务建立标准;UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范,同时也包含一组使企业能将自身提供的Web Service注册,以使别的企业能够发现的访问协议的实现标准。
120、C/S 与 B/S 区别:
答:有如下八个方面的不同:
1.硬件环境不同:
  C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.
  B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行
2.对安全要求不同
  C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.
  B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。
3.对程序架构不同
  C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.
  B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟.
4.软件重用不同
  C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.
  B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子
5.系统维护不同 
  C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统
  B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.
6.处理问题不同
  C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统
  B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小.
7.用户接口不同
  C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
  B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本.
8.信息流不同
  C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低
  B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更像交易中心。
121、什么是web容器
答:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接更容器中的环境变量接**互,不必关注其它系统问题。主要有WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。122、什么是EJB容器
答:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理
123、什么是JNDI
答:(Java Naming & Directory Interface)JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。
124、什么是JMS
答:(Java Message Service)JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。
125、什么是JTA
答:(Java Transaction API)JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。
126、什么是JAF
答:(Java Action FrameWork)JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。
RMI/IIOP:(Remote Method Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。
127、MVC的各个部分都有那些技术来实现?如何实现?
答:MVC是Model-View-Controller的简写。"Model" 代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表示面(由JSP页面产生),"Controller" 是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。
 
 
 
设计模式方面
 
 
 
128、开发中都用到了那些设计模式?用在什么场合?
答:每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心。通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。
129、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法
答:Session Facade Pattern:使用SessionBean访问EntityBean
Message Facade Pattern:实现异步调用
EJB Command Pattern:使用Command JavaBeans取代SessionBean,实现轻量级访问
Data Transfer Object Factory:通过DTO Factory简化EntityBean数据提供特性
Generic Attribute Access:通过AttibuteAccess接口简化EntityBean数据提供特性
Business Interface:通过远程(本地)接口和Bean类实现相同接口规范业务逻辑一致性
EJB架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂,项目队伍越庞大则越能体现良好设计的重要性。
130、j2ee常用的设计模式?说明工厂模式。
 答:Java中的23种设计模式:
Factory(工厂模式),      Builder(建造模式),       Factory Method(工厂方法模式),
Prototype(原始模型模式),Singleton(单例模式),    Facade(门面模式),
Adapter(适配器模式),    Bridge(桥梁模式),        Composite(合成模式),
Decorator(装饰模式),    Flyweight(享元模式),     Proxy(代理模式),
Command(命令模式),      Interpreter(解释器模式), Visitor(访问者模式),
Iterator(迭代子模式),   Mediator(调停者模式),    Memento(备忘录模式),
Observer(观察者模式),   State(状态模式),         Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。
131、UML方面
答:标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图,
UML方面 
 
 
 
CORBA方面
 
 
 
132、CORBA是什么?用途是什么?
答:CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture),由对象管理组织 (Object Management Group,缩写为 OMG)标准化。它的组成是接口定义语言(IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。 其目的为:
用不同的程序设计语言书写
在不同的进程中运行
为不同的操作系统开发
LINUX方面
 
 
 
133、LINUX下线程,GDI类的解释。
答:LINUX实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库中实现。
GDI类为图像设备编程接口类库。
134、LINUX下线程,GDI类的解释。
LINUX实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库中实现。
GDI类为图像设备编程接口类库。
 

谈论 应聘Java笔试时可能出现问题及其答案(第二版 第四部分)

 

引用

应聘Java笔试时可能出现问题及其答案(第二版 第四部分)

应聘Java笔试时可能出现问题及其答案(第二版 第四部分)
代码与编程题
135、写一个Singleton出来
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton {
private Singleton(){}
      //在自己内部定义自己一个实例,是不是很奇怪?
      //注意这是private 只供内部调用
      private static Singleton instance = new Singleton();
      //这里提供了一个供外部访问本class的静态方法,可以直接访问  
      public static Singleton getInstance() {
        return instance;   
      }
    }
    第二种形式:
public class Singleton {
  private static Singleton instance = null;
  public static synchronized Singleton getInstance() {
  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     
  //使用时生成实例,提高了效率!
  if (instance==null)
    instance=new Singleton();
return instance;   }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
136、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?
答:父类:
package test;
public class  FatherClass
{
    public FatherClass()
 {
  System.out.println("FatherClass Create");
 }
}
子类:
package test;
import test.FatherClass;
public class  ChildClass extends FatherClass
{
 public ChildClass()
 {
  System.out.println("ChildClass Create");
 }
 public static void main(String[] args)
 {
  FatherClass fc = new FatherClass();
  ChildClass cc = new ChildClass();
 }
}
输出结果:
C:\>java test.ChildClass
FatherClass Create
FatherClass Create
ChildClass Create

 

137、内部类的实现方式?
答:示例代码如下:
package test;
public class  OuterClass
{
 private class InterClass
 {
  public InterClass()
  {
   System.out.println("InterClass Create");
  }
 }
 public OuterClass()
 {
  InterClass ic = new InterClass();
  System.out.println("OuterClass Create");
 }
 public static void main(String[] args)
 {
  OuterClass oc = new OuterClass();
 }
}
输出结果:
C:\>java test/OuterClass
InterClass Create
OuterClass Create
再一个例题:
public class OuterClass {
  private double d1 = 1.0;
    //insert code here
}
You need to insert an inner class declaration at line 3. Which two inner class declarations are

 

 

valid?(Choose two.)
A. class InnerOne{
     public static double methoda() {return d1;}
   }
B. public class InnerOne{
     static double methoda() {return d1;}
   }
C. private class InnerOne{
     double methoda() {return d1;}
   }
D. static class InnerOne{
     protected double methoda() {return d1;}
   }
E. abstract class InnerOne{
     public abstract double methoda();
   }
说明如下:
一.静态内部类可以有静态成员,而非静态内部类则不能有静态成员。 故 A、B 错
二.静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;return d1 出错。

 

 

故 D 错
三.非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确
四.答案为C、E

 

 

138、Java 的通信编程,编程题(或问答),用JAVA SOCKET编程,读服务器几个字符,再写入本地显示?
答:Server端程序:
package test;
import java.net.*;
import java.io.*;

 

 

public class Server
{
 private ServerSocket ss;
 private Socket socket;
 private BufferedReader in;
 private PrintWriter out;
 public Server()
 {
  try
  {
   ss=new ServerSocket(10000);
   while(true)
   {
    socket = ss.accept();
    String RemoteIP = socket.getInetAddress().getHostAddress();
    String RemotePort = ":"+socket.getLocalPort();
    System.out.println("A client come in!IP:"+RemoteIP+RemotePort);
    in = new BufferedReader(new

 

 

InputStreamReader(socket.getInputStream()));
    String line = in.readLine();
    System.out.println("Cleint send is :" + line);
    out = new PrintWriter(socket.getOutputStream(),true);
    out.println("Your Message Received!");
    out.close();
    in.close();
    socket.close();
   }
  }catch (IOException e)
  {
   out.println("wrong");
  }
 }
 public static void main(String[] args)
 {
  new Server();
 }
};
Client端程序:
package test;
import java.io.*;
import java.net.*;

 

 

public class Client
{
 Socket socket;
 BufferedReader in;
 PrintWriter out;
 public Client()
 {
  try
  {
   System.out.println("Try to Connect to 127.0.0.1:10000");
   socket = new Socket("127.0.0.1",10000);
   System.out.println("The Server Connected!");
   System.out.println("Please enter some Character:");
   BufferedReader line = new BufferedReader(new

 

 

InputStreamReader(System.in));
   out = new PrintWriter(socket.getOutputStream(),true);
   out.println(line.readLine());
   in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
   System.out.println(in.readLine());
   out.close();
   in.close();
   socket.close();
  }catch(IOException e)
  {
   out.println("Wrong");
  }
 }
 public static void main(String[] args)
 {
  new Client();
 }
};

 

 

139、用JAVA实现一种排序,JAVA类实现序列化的方法(二种)? 如在COLLECTION框架中,实现比较要实现什么样的接口?
答:用插入法进行排序代码如下
package test;
import java.util.*;
class  InsertSort
{
 ArrayList al;
 public InsertSort(int num,int mod)
 {
  al = new ArrayList(num);
  Random rand = new Random();
  System.out.println("The ArrayList Sort Before:");
  for (int i=0;i<num ;i++ )
  {
   al.add(new Integer(Math.abs(rand.nextInt()) % mod + 1));
   System.out.println("al["+i+"]="+al.get(i));
  }
 }
 public void SortIt()
 {
  Integer tempInt;
  int MaxSize=1;
  for(int i=1;i<al.size();i++)
  {
       tempInt = (Integer)al.remove(i);
    if(tempInt.intValue()>=((Integer)al.get(MaxSize-1)).intValue())
    {
     al.add(MaxSize,tempInt);
     MaxSize++;
     System.out.println(al.toString());
    } else {
     for (int j=0;j<MaxSize ;j++ )
     {
      if

 

 

(((Integer)al.get(j)).intValue()>=tempInt.intValue())
      {
       al.add(j,tempInt);
       MaxSize++;
       System.out.println(al.toString());
       break;
      }
     }
    }
  }
  System.out.println("The ArrayList Sort After:");
  for(int i=0;i<al.size();i++)
  {
   System.out.println("al["+i+"]="+al.get(i));
  }
 }
 public static void main(String[] args)
 {
  InsertSort is = new InsertSort(10,100);
  is.SortIt();
 }
}
140、编程:编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。
答:代码如下:
package test;

 

 

class  SplitString
{
 String SplitStr;
 int SplitByte;
 public SplitString(String str,int bytes)
 {
  SplitStr=str;
  SplitByte=bytes;
  System.out.println("The String is:'"+SplitStr+"';SplitBytes="+SplitByte);
 }
 public void SplitIt()
 {
  int loopCount;
  

 

 

loopCount=(SplitStr.length()%SplitByte==0)?(SplitStr.length()/SplitByte):(SplitStr.length()/Split

 

 

Byte+1);
  System.out.println("Will Split into "+loopCount);
  for (int i=1;i<=loopCount ;i++ )
  {
   if (i==loopCount){
    

 

 

System.out.println(SplitStr.substring((i-1)*SplitByte,SplitStr.length()));
   } else {
    

 

 

System.out.println(SplitStr.substring((i-1)*SplitByte,(i*SplitByte)));
   }
  }
 }
 public static void main(String[] args)
 {
  SplitString ss = new SplitString("test中dd文dsaf中男大3443n中国43中国人

 

 

0ewldfls=103",4);
  ss.SplitIt();
 }
}

 

 

141、JAVA多线程编程。 用JAVA写一个多线程程序,如写四个线程,二个加1,二个对一个变量减一,输出。
希望大家补上,谢谢

 

 

142、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询.
答:程序如下:
package hello.ant;
import java.sql.*;
public class  jdbc
{
 String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl";
 String theUser="admin";
 String thePw="manager";
 Connection c=null;
 Statement conn;
 ResultSet rs=null;
 public jdbc()
 {
  try{
    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
          c = DriverManager.getConnection(dbUrl,theUser,thePw);
    conn=c.createStatement();
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 public boolean executeUpdate(String sql)
 {
   try
   {
     conn.executeUpdate(sql);
     return true;
   }
   catch (SQLException e)
   {
     e.printStackTrace();
     return false;
   }
 }
 public ResultSet executeQuery(String sql)
 {
   rs=null;
   try
   {
     rs=conn.executeQuery(sql);
   }
   catch (SQLException e)
   {
     e.printStackTrace();
   }
   return rs;
 }
 public void close()
 {
   try
   {
     conn.close();
     c.close();
   }
   catch (Exception e)
   {
     e.printStackTrace();
   }
 }
 public static void main(String[] args)
 {
  ResultSet rs;
  jdbc conn = new jdbc();
  rs=conn.executeQuery("select * from test");
  try{
  while (rs.next())
  {
   System.out.println(rs.getString("id"));
   System.out.println(rs.getString("name"));
  }
  }catch(Exception e)
  {
   e.printStackTrace();
  }
 }
}

 

 

143、ORACLE大数据量下的分页解决方法。一般用截取ID方法,还有是三层嵌套方法。
答:一种分页方法
<%
  int i=1;
  int numPages=14;
  String pages = request.getParameter("page") ;
  int currentPage = 1;
  currentPage=(pages==null)?(1):{Integer.parseInt(pages)}
  sql = "select count(*) from tables";
  ResultSet rs = DBLink.executeQuery(sql) ;
  while(rs.next()) i = rs.getInt(1) ;
  int intPageCount=1;
  intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1);
  int nextPage ;
  int upPage;
  nextPage = currentPage+1;
  if (nextPage>=intPageCount) nextPage=intPageCount;
  upPage = currentPage-1;
  if (upPage<=1) upPage=1;
  rs.close();
  sql="select * from tables";
  rs=DBLink.executeQuery(sql);
  i=0;
  while((i<numPages*(currentPage-1))&&rs.next()){i++;}
%>
//输出内容
//输出翻页连接
合计:<%=currentPage%>/<%=intPageCount%><a href="List.jsp?page=1">第一页</a><a

 

 

href="List.jsp?page=<%=upPage%>">上一页</a>
<%
  for(int j=1;j<=intPageCount;j++){
  if(currentPage!=j){
%>
  <a href="list.jsp?page=<%=j%>">[<%=j%>]</a>
<%
  }else{
  out.println(j);
  }
  }
%>
<a href="List.jsp?page=<%=nextPage%>">下一页</a><a href="List.jsp?page=<%=intPageCount%>">最后页

 

 

</a>

 

 

144、用jdom解析xml文件时如何解决中文问题?如何解析?
答:看如下代码,用编码方式加以解决
package test;
import java.io.*;
public class DOMTest
{
 private String inFile = "c:\\people.xml";
 private String outFile = "c:\\people.xml";
 public static void main(String args[])
 {
     new DOMTest();
    }
 public DOMTest()
 {
  try
     {
      javax.xml.parsers.DocumentBuilder builder =
       

 

 

javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
      org.w3c.dom.Document doc = builder.newDocument();
      org.w3c.dom.Element root = doc.createElement("老师");
      org.w3c.dom.Element wang = doc.createElement("王");
   org.w3c.dom.Element liu = doc.createElement("刘");
      wang.appendChild(doc.createTextNode("我是王老师"));
      root.appendChild(wang);
      doc.appendChild(root);
      javax.xml.transform.Transformer transformer =
       javax.xml.transform.TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312");
      transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");  

 

 

  
      transformer.transform(new javax.xml.transform.dom.DOMSource(doc),
            new

 

 

javax.xml.transform.stream.StreamResult(outFile));
     }
     catch (Exception e)
     {
      System.out.println (e.getMessage());
     }
    }
}

 

 

145、编程用JAVA解析XML的方式.
答:用SAX方式解析XML,XML文件如下:
<?xml version="1.0" encoding="gb2312"?>
<person>
  <name>王小明</name>
  <college>信息学院</college>  
  <telephone>6258113</telephone>
  <notes>男,1955年生,博士,95年调入海南大学</notes>
 </person>
 事件回调类SAXHandler.java
 import java.io.*;
import java.util.Hashtable;
import org.xml.sax.*;
public class SAXHandler extends HandlerBase
  {
  private Hashtable table = new Hashtable();
  private String currentElement = null;
  private String currentValue = null;
  public void setTable(Hashtable table)
    {
    this.table = table;
    }
  public Hashtable getTable()
    {
    return table;
    }
  public void startElement(String tag, AttributeList attrs)
  throws SAXException
    {
    currentElement = tag;
    }
  public void characters(char[] ch, int start, int length)
  throws SAXException
    {
    currentValue = new String(ch, start, length);
    }
  public void endElement(String name) throws SAXException
    {
    if (currentElement.equals(name))
      table.put(currentElement, currentValue);
    }
  }
JSP内容显示源码,SaxXml.jsp:
<HTML>
<HEAD>
<TITLE>剖析XML文件people.xml</TITLE>
</HEAD>
<BODY>
<%@ page errorPage="ErrPage.jsp"
contentType="text/html;charset=GB2312" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Hashtable" %>
<%@ page import="org.w3c.dom.*" %>
<%@ page import="org.xml.sax.*" %>
<%@ page import="javax.xml.parsers.SAXParserFactory" %>
<%@ page import="javax.xml.parsers.SAXParser" %>
<%@ page import="SAXHandler" %>
<%
File file = new File("c:\\people.xml");
FileReader reader = new FileReader(file);
Parser parser;
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
SAXHandler handler = new SAXHandler();
sp.parse(new InputSource(reader), handler);
Hashtable hashTable = handler.getTable();
out.println("<TABLE BORDER=2><CAPTION>教师信息表</CAPTION>");
out.println("<TR><TD>姓名</TD>" + "<TD>" +
  (String)hashTable.get(new String("name")) + "</TD></TR>");
out.println("<TR><TD>学院</TD>" + "<TD>" +
  (String)hashTable.get(new String("college"))+"</TD></TR>");
out.println("<TR><TD>电话</TD>" + "<TD>" +
  (String)hashTable.get(new String("telephone")) + "</TD></TR>");
out.println("<TR><TD>备注</TD>" + "<TD>" +
  (String)hashTable.get(new String("notes")) + "</TD></TR>");
out.println("</TABLE>");
%>
</BODY>
</HTML>

 

 

146、EJB的基本架构
答:一个EJB包括三个部分:
  Remote Interface 接口的代码
  package Beans;
  import javax.ejb.EJBObject;
  import java.rmi.RemoteException;
  public interface Add extends EJBObject
  {
   //some method declare
  }
  Home Interface 接口的代码
  package Beans;
  import java.rmi.RemoteException;
  import jaax.ejb.CreateException;
  import javax.ejb.EJBHome;
  public interface AddHome extends EJBHome
  {
    //some method declare
  }
  EJB类的代码
  package Beans;
  import java.rmi.RemoteException;
  import javax.ejb.SessionBean;
  import javx.ejb.SessionContext;
  public class AddBean Implements SessionBean
  {
    //some method declare
  } 

 

 

147、如何校验数字型?
var re=/^\d{1,8}$|\.\d{1,2}$/;
var str=document.form1.all(i).value;
var r=str.match(re);
if (r==null)
{
   sign=-4;
   break;
}
else{
   document.form1.all(i).value=parseFloat(str);
}

 

 

148、将一个键盘输入的数字转化成中文输出
(例如:输入:1234567     输出:一百二拾三万四千五百六拾七)
用java语言实现,,请编一段程序实现!
 public class Reader {
  private String strNum;
  private String strNumChFormat;
  private String strNumTemp;
  private int intNumLen;
  private String strBegin;
  public Reader(String strNum) {
    this.strNum = strNum;
  }
  public boolean check(String strNum) {
    boolean valid = false;
   
    if (strNum.substring(0,1).equals("0")){
     this.strNum = strNum.substring(1);
    }
    try {
      new Double(strNum);
      valid = true;
    }
    catch (NumberFormatException ex) {
      System.out.println("Bad number format!");
    }
    return valid;
  }
  public void init() {
    strNumChFormat = "";
    intNumLen = strNum.length();
    strNumTemp = strNum;
    strNumTemp = strNumTemp.replace('1', '一');
    strNumTemp = strNumTemp.replace('2', '二');
    strNumTemp = strNumTemp.replace('3', '三');
    strNumTemp = strNumTemp.replace('4', '四');
    strNumTemp = strNumTemp.replace('5', '五');
    strNumTemp = strNumTemp.replace('6', '六');
    strNumTemp = strNumTemp.replace('7', '七');
    strNumTemp = strNumTemp.replace('8', '八');
    strNumTemp = strNumTemp.replace('9', '九');
    strNumTemp = strNumTemp.replace('0', '零');
    strNumTemp = strNumTemp.replace('.', '点');
    strBegin = strNumTemp.substring(0, 1);
  }
  public String readNum() {
    if (check(strNum)) {
      init();
      try {
        for (int i = 1, j = 1, k = 1; i < intNumLen; i++) {
          if (strNumTemp.charAt(intNumLen - 1) == '零' && i == 1) {
            strNumChFormat = "位";
          }
          else if (strNumTemp.charAt(intNumLen - i) == '零' && j == 1) {
            strNumChFormat = "位" + strNumChFormat;
          }
          else if (strNumTemp.charAt(intNumLen - i) == '点') {
            j = 1;
            k = 1;
            strNumChFormat = strNumTemp.charAt(intNumLen - i) + strNumChFormat;
            continue;
          }
          else {
            strNumChFormat = strNumTemp.charAt(intNumLen - i) + strNumChFormat;
          }
          if (strNumTemp.charAt(intNumLen - i - 1) != '位' &&
              strNumTemp.charAt(intNumLen - i - 1) != '零') {
            if (j == 1 && i < intNumLen) {
              strNumChFormat = '拾' + strNumChFormat;
            }
            else if (j == 2 && i < intNumLen) {
              strNumChFormat = '百' + strNumChFormat;
            }
            else if (j == 3 && i < intNumLen) {
              strNumChFormat = '千' + strNumChFormat;
            }
          }
          if (j == 4 && i < intNumLen) {
            j = 0;
          }
          if (k == 4 && i < intNumLen) {
            strNumChFormat = '万' + strNumChFormat;
          }
          else if (k == 8 && i < intNumLen) {
            k = 0;
            strNumChFormat = '亿' + strNumChFormat;
          }
          j++;
          k++;
        }
        while (strNumChFormat.indexOf("位") != -1) {
          strNumChFormat = strNumChFormat.replaceAll("位", " ");
        }
        if (strNumChFormat.substring(0, 2) == "一拾") {
          strNumChFormat = strNumChFormat.substring(1, strNumChFormat.length());
        }
        if (strNumChFormat.indexOf("点") >= 0) {
          String rebegin = strNumChFormat.substring(0,
              strNumChFormat.indexOf("点"));
          String relast = strNumChFormat.substring(strNumChFormat.indexOf("点"),
              strNumChFormat.length());
          for (int i = 1; i <= relast.length(); i++) {
            relast = relast.replaceAll("拾", "");
            relast = relast.replaceAll("百", "");
            relast = relast.replaceAll("千", "");
            relast = relast.replaceAll("万", "");
            relast = relast.replaceAll("亿", "");
          }
          strNumChFormat = rebegin + relast;
        }
      }
      catch (ArrayIndexOutOfBoundsException ex) {
        ex.printStackTrace();
      }
      catch (Exception ex) {
        ex.printStackTrace();
      }
      int off = strNumChFormat.indexOf("点");
      strNumChFormat = strBegin + strNumChFormat.substring(0);
    }
    else {
      strNumChFormat = "";
    }
    return strNumChFormat;
  }
  public static void main(String args[]) {
    try {
      String number = args[0].toString();
      System.out.println("The number is: " + number);
      Reader reader = new Reader(number);
      System.out.println("Output String: " + reader.readNum());
    }
    catch (Exception ex) {
      System.out.println("Please input like that: javac Reader <number>");
    }
  }
}

 

 

149、JAVA代码查错
1.
abstract class Name {
   private String name;
   public abstract boolean isStupidName(String name) {}
}
大侠们,这有何错误?
答案: 错。abstract method必须以分号结尾,且不带花括号。
2.
public class Something {
   void doSomething () {
       private String s = "";
       int l = s.length();
   }
}
有错吗?
答案: 错。局部变量前不能放置任何访问修饰符 (private,public,和protected)。final可以用来修饰局部变量
(final如同abstract和strictfp,都是非访问修饰符,strictfp只能修饰class和method而非variable)。
3.
abstract class Something {
   private abstract String doSomething ();
}
这好像没什么错吧?
答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的,怎么可以用private把abstract
method封锁起来呢? (同理,abstract method前不能加final)。
4.
public class Something {
   public int addOne(final int x) {
       return ++x;
   }
}
这个比较明显。
答案: 错。int x被修饰成final,意味着x不能在addOne method中被修改。
5.
public class Something {
   public static void main(String[] args) {
       Other o = new Other();
       new Something().addOne(o);
   }
   public void addOne(final Other o) {
       o.i++;
   }
}
class Other {
   public int i;
}
和上面的很相似,都是关于final的问题,这有错吗?
答案: 正确。在addOne method中,参数o被修饰成final。如果在addOne method里我们修改了o的reference
(比如: o = new Other();),那么如同上例这题也是错的。但这里修改的是o的member vairable
(成员变量),而o的reference并没有改变。
6.
class Something {
    int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
}
有什么错呢? 看不出来啊。
答案: 正确。输出的是"i = 0"。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。int的default value是0。
7.
class Something {
    final int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
}
和上面一题只有一个地方不同,就是多了一个final。这难道就错了吗?
答案: 错。final int i是个final的instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为"final int i = 0;"。
8.
public class Something {
     public static void main(String[] args) {
        Something s = new Something();
        System.out.println("s.doSomething() returns " + doSomething());
    }
    public String doSomething() {
        return "Do something ...";
    }
}
 看上去很完美。
答案: 错。看上去在main里call doSomething没有什么问题,毕竟两个methods都在同一个class里。但仔细看,main是static的。static method不能直接call non-static methods。可改成"System.out.println("s.doSomething() returns " + s.doSomething());"。同理,static method不能访问non-static instant variable。
9.
此处,Something类的文件名叫OtherThing.java
class Something {
    private static void main(String[] something_to_do) {       
        System.out.println("Do something ...");
    }
}
 这个好像很明显。
答案: 正确。从来没有人说过Java的Class名字必须和其文件名相同。但public class的名字必须和文件名相同。
10.
interface  A{
   int x = 0;
}
class B{
   int x =1;
}
class C extends B implements A {
   public void pX(){
      System.out.println(x);
   }
   public static void main(String[] args) {
      new C().pX();
   }
}
答案:错误。在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未明确的x调用,两个x都匹配(就象在同时import java.util和java.sql两个包时直接声明Date一样)。对于父类的变量,可以用super.x来明确,而接口的属性默认隐含为 public static final.所以可以通过A.x来明确。
11.
interface Playable {
    void play();
}
interface Bounceable {
    void play();
}
interface Rollable extends Playable, Bounceable {
    Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
    private String name;
    public String getName() {
        return name;
    }
    public Ball(String name) {
        this.name = name;       
    }
   public void play() {
        ball = new Ball("Football");
        System.out.println(ball.getName());
    }
}
这个错误不容易发现。
答案: 错。"interface Rollable extends Playable, Bounceable"没有问题。interface可继承多个interfaces,所以这里没错。问题出在interface Rollable里的"Ball ball = new Ball("PingPang");"。任何在interface里声明的interface variable (接口变量,也可称成员变量),默认为public static final。也就是说"Ball ball = new Ball("PingPang");"实际上是"public static final Ball ball = new Ball("PingPang");"。在Ball类的Play()方法中,"ball = new Ball("Football");"改变了ball的reference,而这里的ball来自Rollable interface,Rollable interface里的ball是public static final的,final的object是不能被改变reference的。因此编译器将在"ball = new Ball("Football");"这里显示有错。
28、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。
public class ThreadTest1{
  private int j;
  public static void main(String args[]){
ThreadTest1 tt=new ThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(int i=0;i<2;i++){
Thread t=new Thread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
  private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
  }
  private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
  }
  class Inc implements Runnable{
public void run(){
for(int i=0;i<100;i++){
inc();
}
}
  }
  class Dec implements Runnable{
public void run(){
for(int i=0;i<100;i++){
dec();
}
 }
  }
}

6月17日

失望之政府不作为

 
     网络上第一次出现山西黑砖窑报道时,我还在想现在网络真的是越来越乱,记者为了吸引眼球越来越不负责任了,现在的社会怎么会出现奴隶社会才会有的东西。还真没想到,在现在的文明社会里,在整天以人民公仆,人民的儿子自居的政府治下,还就出现了这种非文明事件。
    其实我关注的倒不是死了几个人,黑砖窑的主人有多黑心,因为人的本性是贪婪的,只不过这帮披着人皮的畜生贪欲更旺盛罢了。我关注的是政府到哪里去了,他们的职能部门在做什么,难道山西至今还是不毛之地,还没有政府?
    先不说他们对企业的监督责任,为什么收税的时候,再隐蔽的角落里的企业,他们也能掘地三尺?为什么企业违法犯罪的时候,他们就一个个睁眼瞎了呢?说实话,我倒是希望是政府监督失责,因为这说明他们还在做事情,只是没有做好罢了。我怕令人失望的是,他们没有失责,他们对这些企业所作所为一清二楚,而是不去管,并且充当保护伞。
    退一万步讲,当地政府为了税收,为了功绩,睁一眼闭一眼,掩盖企业恶行也就算了。但是当人家父母来认领自己的孩子了,你怎么还不赶快回到你的公仆身份,回到你的儿子身份上,哪怕是摆摆样子呢?竟然阻止人家来领孩子,甚至他们再转卖刚解救出来的孩子。真真的是令人发指了,他们不是我们的公仆,也不是我们的儿子,甚至也不是我们的父母官,因为他们根本就不是人,真是奇怪了,山西是从哪里找出这样的基因变异的人的,也没听说山西有过核爆,有过核污染啊。
    再往上追,网络,报纸各种媒体报道的沸沸扬扬,难道当地的市政府,省政府的那些还没有变异的太厉害的官员都是聋子,都是瞎子吗?报道那么多天,怎么他们连屁都不放一个?非得等到国家领导发话了,他们才去做,如果什么都要等国家领导人去做,那这些省府官员,市府官员是做什么的呢?也许他们是为了凸显国家领导人更爱民罢,我暂且这样想。
    我们的国家是人民当家做主的国家,这是宪法里开宗明义了的。况且旧社会里都知道水能载舟,亦能覆舟。请政府里的这些大老爷有点作为吧,毕竟新中国建立了还不到一百年,我实实在在的不想我都能看到不想看到的覆舟那一天。
    另:媒体积极主动挖掘这些是好的,但是希望媒体直击要害。唉,真不希望这件事情的最后结局是:在国家领导人亲自关注下,在当地政府的大力支持下,在当地公安的不怕流血,不怕牺牲下,英勇作战,完美的解救人民与水火中,充分体现了国家,政府对人民,对民工的关怀之情,当地人民纷纷赞扬,感激政府对他们的救助......
6月3日

朱广沪,你脸皮还要厚到什么程度?

 
     敬爱的猪爷,您的脸皮真的比猪的皮还要厚吗?看看您老的勇气,连亚洲三流的泰国队您都敢输,让我一直自豪地坚持中国队是亚洲三流的信念受到了严重打击,原来连三流都不能算!
     您老真是太厉害了,今天早上同美国队的比赛让我对您的敬仰真是更上一层楼,尤其是您高超的指挥艺术和对自己人的关照,更是让我佩服的五体投地,地球人都知道董方卓是前锋,可您偏偏独具慧眼,在他身上发掘出了边前卫的潜质,我想连弗爵爷都要伸大拇指了,更让人感人肺腑的是您对李铁的信任简直超过了您对您父母的层次。李铁都好几年没打过比赛了,可他在您心里硬是个宝,您真的把国家队当自家自留地了吗,想种啥就种啥,甚至是搞异种嫁接玩?
     猪爷,您也老大不小了,真的连这点自知之明都没有吗,难道国家队真的那么值得您留恋,外面的世界真的那么精彩吗?求求您,还是赶快回到猪窝吃您的猪食吧,我不想我刚刚更新过的中国队亚洲四流信念再次受到打击。
     真的,求求您了!
5月26日

5月小结

 
     5月就要结束了,总结一下这个月的工作,生活吧。
     先是我关注的英超联赛结束了,我喜欢的切尔西拿到了足总杯,但是很遗憾的是没能拿到联赛冠军,不过也没什么,在这么困难的局面下能取得这样的成绩,已经很好了,我为它感到骄傲!冠军杯也结束了,更应该取得冠军的利物浦没能夺冠,这也许是还债吧,在江湖上混,迟早是要还的.
     工作上,上电门户这个重头项目总算有个可以说的过去的成果了,从四月进入项目到现在两个月了,也曾经历尽艰辛,怀疑过,但是还是在团队的团结特别是因为有一个比较牛的项目经理的带领下,项目得以顺利进行,我也算是有所收获吧,熟悉了sap portal,可以熟练做portal的部署,从中也不仅是学习到了portal的知识,也知道了怎么去学习。特别要提的是这个项目根本没有可以借鉴的东西,甚至无所不能的google老师都不能提供给我更多一点资料,只有sap网站的help。这两个月里,我每天所做的就是阅读英文文档,然后实践,在查资料,再实践。其中的艰辛真的是一言难尽。不过这些都过去了,项目后半段会比较轻松吧,我想。
   心中总是有股说不出的苦闷。还是借苏轼老先生的句子来结束这份小结吧。
   “渺渺兮予怀,望美人兮天一方”

hibernate中对clob类型的处理

 
    这里主要介绍的是对clob的存储,因为读取比较容易。代码如下
    Session session = dao.getSession();
   Transaction tx = session.beginTransaction();
   information.setInfoBody(Hibernate.createClob(" "));
   session.update(information);
   session.flush();
   session.refresh(information, LockMode.UPGRADE);
   
   String infoText = information.getInfoText();
   SerializableClob serializableClob = (SerializableClob) information
     .getInfoBody();
   CLOB clob = (CLOB) serializableClob.getWrappedClob();
   clob.putString(1, infoText);
   tx.commit();
    这里主要要注意的就是先存储一个空的clob之后一定要flush一下,然后在存储真正的内容。
5月11日

如何获取指定月份的天数

  
       近日在项目里的一个小模块中遇到一个获取指定月份天数的小问题,一时之间还真没有办法,相信不少java新手也会遇到和我相似的问题。现在将解决办法公布如下:
    Calendar   calendar=Calendar.getInstance();  
    calendar.set(Calendar.MONTH,3);   //这里是设置为当年的3月份,如果不是当年,还要设置年份
    System.out.println(calendar.getActualMaximum(Calendar.DATE));
5月6日

java好用的小工具

1,Java剖析工具 -- profiler
  是一个全功能的Java剖析工具(profiler),专用于分析J2SE和J2EE应用程序。它把CPU、执行绪和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合用途。JProfiler直觉式的GUI让你可以找到效能瓶颈、抓出内存漏失 (memory leaks)、并解决执行绪的问题。它让你得以对heap walker作资源回收器的root analysis,可以轻易找出内存漏失;heap快照(snapshot)模式让未被参照(reference)的对象、稍微被参照的对象、或在终结(finalization)队列的对象都会被移除;整合精灵以便剖析浏览器的Java外挂功能。
下载地址:http://www.ej-technologies.com/download/overview.html
2,冗余代码检查 -- Simian
  Simian UI 是一个用来发现重复代码的eclipse插件,对于改善设计,消除冗余代码很有帮助。
安装方法:使用eclipse的Help->Software Update进行安装。站点地址为:http://www.integility.com/eclipse/
安装后,按照提示重新启动eclipse。在希望进行分析的项目上点击右键,选择Simian->Add Simian to this project,就可以为该项目进行代码检查。

  
4月8日

永远不要放弃希望

 
     在英超进行到第32轮的时候,曼联还领先6分,而且状态正佳,对手又是朴茨茅斯,谁又能想到会输球呢?作为切尔西的球迷,我都要放弃希望了。
     然而切尔西人在做什么,他们什么也不说,只是在默默的做着自己应该做的事情,绝不放弃,努力踢好每场球,然后等待对手犯错误,他们能做的就是这些。
     不要嘲笑机会主义者,因为他们不仅仅是在等待机会,而且还要为机会做准备。
     切尔西就做到了,现在仅相差3分,而曼联状态开始下滑,切尔西正在好转,不能说以后不再出现这样的机会。
     在我们的生活中也是,不能因为机会渺茫就放弃希望,我们要积极的去准备,这样机会来临时我们才能抓住它!