星期六, 九月 22, 2007

2007 MotoRola

2007年摩托罗拉笔试题
1.介绍一下STL,详细说明STL如何实现vector。
Answer:
STL (标准模版库,Standard Template Library.它由容器算法迭代器组成。
STL有以下的一些优点:
可以方便容易地实现搜索数据或对数据排序等一系列的算法;
调试程序时更加安全和方便;
即使是人们用STL在UNIX平台下写的代码你也可以很容易地理解(因为STL是跨平台的)。

vector实质上就是一个动态数组,会根据数据的增加,动态的增加数组空间。

2.如果用VC开发程序,常见这么几个错误,C2001,c2005,c2011,这些错误的原因是什么。
Answer:
  在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:
  unresolved external symbol “symbol”(不确定的外部“符号”)。
  如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或标签,将产生此
错误消息。

一般来说,发生错误的原因有两个:一是所引用的函数、变量不存在、拼写不正确或者使用
错误;其次可能使用了不同版本的连接库。

编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难
解决的错误.

3.继承和委派有什么分别,在决定使用继承或者委派的时候需要考虑什么。
在OOD,OOP中,组合优于继承.
当然多态的基础是继承,没有继承多态无从谈起。

当对象的类型不影响类中函数的行为时,就要使用模板来生成这样一组类。
当对象的类型影响类中函数的行为时,就要使用继承来得到这样一组类.

4.指针和引用有什么分别;如果传引用比传指针安全,为什么?如果我使用常量指针难道不
行吗?
(1) 引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初
始化,可以在定义后面的任何地方重新赋值.
(2) 不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL.
(3) 引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任
何时候都可以改变为指向另一个对象.给引用赋值并不是改变它和原始对象的绑定关系.
(4) 引用的创建和销毁并不会调用类的拷贝构造函数
(5) 语言层面,引用的用法和对象一样;在二进制层面,引用一般都是通过指针来实现的,
只不过编译器帮我们完成了转换.

不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引
用,显得很安全。
const 指针仍然存在空指针,并且有可能产生野指针.

总的来说:引用既具有指针的效率,又具有变量使用的方便性和直观性.

5.参数传递有几种方式;实现多态参数传递采用什么方式,如果没有使用某种方式原因是什
么;
传值,传指针或者引用

6.结合一个项目说明你怎样应用设计模式的理念。
设计模式更多考虑是扩展和重用,而这两方面很多情况下,往往会被忽略。
不过,我不建议滥用设计模式,以为它有可能使得简单问题复杂化.

7.介绍一下你对设计模式的理解。(这个过程中有很多很细节的问题随机问的)
设计模式概念是由建筑设计师Christopher Alexander提出:"每一个模式描述了一个在我们
周围不断重复发生的问题,以及该问题的解决方案的核心.这样,你就能一次又一次地使用该
方案而不必做重复劳动."上述定义是对设计模式的广义定义.将其应用到面向对象软件的领
域内,就形成了对设计模式的狭义定义.
可以简单的认为:设计模式就是解决某个特定的面向对象软件问题的特定方法, 并且已经上
升到理论程度。

框架与设计模式的区别:
1,设计模式和框架针对的问题域不同.设计模式针对面向对象的问题域;框架针对特定业务的
问题域
2,设计模式比框架更为抽象.设计模式在碰到具体问题后,才能产生代码;框架已经可以用代
码表示
3,设计模式是比框架更小的体系结构元素.框架中可以包括多个设计模式
设计模式就像武术中基本的招式.将这些招式合理地纵组合起来,就形成套路(框架),框架是
一种半成品.

8.C++和C定义结构的分别是什么。
C language 的结构仅仅是数据的结合
C plus plus的struct 和 class 其实具备几乎一样的功能,只是默认的访问属性不一样而
已。

9.构造函数可否是虚汗数,为什么?析构函数呢,可否是纯虚的呢?
构造函数不能为虚函数,要构造一个对象,必须清楚地知道要构造什么,否则无法构造一个
对象。
析构函数可以为纯虚函数。

10,拷贝构造函数相关问题,深拷贝,浅拷贝,临时对象等。
深拷贝意味着拷贝了资源和指针,而浅拷贝只是拷贝了指针,没有拷贝资源
这样使得两个指针指向同一份资源,造成对同一份析构两次,程序崩溃。

临时对象的开销比局部对象小些。

11.结合1个你认为比较能体现OOP思想的项目,用UML来描述。(最好这个项目继承,多态,
虚函数都有体现)这个问题大概会占面试时间的一半,并且会问很多问题,一不小心可能会
被问住)。
。。。

12。基类的有1个虚函数,子类还需要申明为virtual吗?为什么。
不申明没有关系的。
不过,我总是喜欢显式申明,使得代码更加清晰。

13.C也可以通过精心封装某些函数功能实现重用,那C++的类有什么优点吗,难道仅仅是为
实现重用。
并不仅仅是这样的。
OOD,OOP从根本上改变了程序设计模式和设计思想,具备重大和深远的意义。
类的三大最基本的特征:封装,继承,多态.

14.C++特点是什么,如何实现多态?画出基类和子类在内存中的相互关系。
多态的基础是继承,需要虚函数的支持,简单的多态是很简单的。

子类继承父类大部分的资源,不能继承的有构造函数,析构函数,拷贝构造函数,
operator=函数,友元函数等等

15.为什么要引入抽象基类和纯虚函数?
主要目的是为了实现一种接口的效果。

16.介绍一下模板和容器。如何实现?(也许会让你当场举例实现)
模板可以说比较古老了,但是当前的泛型编程实质上就是模板编程。
它体现了一种通用和泛化的思想。

STL有7种主要容器:vector,list,deque,map,multimap,set,multiset.

17.你如何理解MVC。简单举例来说明其应用。
MVC模式是observer 模式的一个特例,典型的有MFC里面的文档视图架构。

18,多重继承如何消除向上继承的二义性。
使用虚拟继承即可.

星期五, 九月 21, 2007

Design Pattern

Abstract Factory( 3 . 1 ):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它
们具体的类。
A d a p t er ( 4 . 1 ):将一个类的接口转换成客户希望的另外一个接口。A d a p t e r模式使得原本
由于接口不兼容而不能一起工作的那些类可以一起工作。
B r i d g e( 4 . 2 ):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
B u i l d e r( 3 . 2 ):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不
同的表示。
Chain of Responsibility( 5 . 1 ):为解除请求的发送者和接收者之间耦合,而使多个对象都
有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象
处理它。
C o m m a n d( 5 . 2 ):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数
化;对请求排队或记录请求日志,以及支持可取消的操作。
C o m p o s i t e( 4 . 3 ):将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e使
得客户对单个对象和复合对象的使用具有一致性。
D e c o r a t o r( 4 . 4 ):动态地给一个对象添加一些额外的职责。就扩展功能而言, D e c o r a t o r模
式比生成子类方式更为灵活。
F a c a d e( 4 . 5 ):为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层
接口,这个接口使得这一子系统更加容易使用。
Factory Method( 3 . 3 ):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。
Factory Method使一个类的实例化延迟到其子类。
F l y w e i g h t( 4 . 6 ):运用共享技术有效地支持大量细粒度的对象。
I n t e r p r e t e r( 5 . 3 ):给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释
器使用该表示来解释语言中的句子。
I t e r a t o r( 5 . 4 ):提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的
内部表示。
M e d i a t o r( 5 . 5 ):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式
地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
M e m e n t o( 5 . 6 ):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外
保存这个状态。这样以后就可将该对象恢复到保存的状态。
O b s e r v e r( 5 . 7 ):定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并自动刷新。
P r o t o t y p e( 3 . 4 ):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对
象。
P r o x y( 4 . 7 ):为其他对象提供一个代理以控制对这个对象的访问。
S i n g l e t o n( 3 . 5 ):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
S t a t e( 5 . 8 ):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它
所属的类。
S t r a t e g y (5 . 9 ):定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模
式使得算法的变化可独立于使用它的客户。
Template Method( 5 . 1 0 ):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Vi s i t o r( 5 . 11 ):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元
素的类的前提下定义作用于这些元素的新操作。

星期四, 九月 20, 2007

使用带密钥库的PFX和PEM证书格式

作者:Arvind Tiwari
本文关键字:pem, pfx, jks, keystore, certificate, conversion, java keystore, two way ssl, Dev Toolbox, WebLogic Server, Arvind Tiwari, 密钥库, 证书, 转换


  公钥加密技术12号标准(Public Key Cryptography Standards #12,PKCS#12)为存储和传输用户或服务器私钥、公钥和证书指定了一个可移植的格式。它是一种二进制格式,这些文件也称为PFX文件。开发人员通常需要将PFX文件转换为某些不同的格式,如PEM或JKS,以便可以为使用SSL通信的独立Java客户端或WebLogic Server使用。本文描述如何从PFX文件导出私钥、公钥和证书并用它们创建JKS或PEM文件。

简介

  创建的PFX证书通常用来满足两个目的:

  1. 客户端证书:该证书通常安装在客户端的浏览器上,向其他终端的服务器提供用户身份。它还向服务器提供一个公钥和证书。服务器将使用该公钥来加密这些两个端点之间的任何数据交换。
  2. 服务器证书:该证书将安装在服务器端,向尝试建立连接的客户端提供服务器身份、证书和公钥信息。使用证书和公钥来进行客户端和服务器之间的信息交换和进一步的数据加密。

  不过,PFX并不是惟一使用的证书格式。我们来看看以下几种格式。

  • 增强型私人邮件(Privacy Enhanced Mail,PEM)格式现在更多地用作密钥格式,并且可以包含私钥(RSA和DSA)、公钥(RSA和DSA)和x509证书。它存储ASCII头部包装的Base64编码DER格式的数据,所以它适用于系统之间的文本模式传输。
  • 分布式编码规则(Distinguished Encoding Rules,DER)格式也可以包含私钥、公钥和证书。它是大多数浏览器的默认格式,并且按照ASN1 DER格式进行存储。它没有头部——PEM是文本头部包装的DER。

  WebLogic Server除了证书库之外,不需要特定的证书格式。在WebLogic Server上安装SSL需要Java密钥库(Java Key Store,JKS)文件中存储的服务器证书。JKS文件仅用于存储服务器证书、私钥、公钥和身份证书。

   以下是我们需要从PFX证书格式转换时的两种情况:

  1. 将服务器证书(私钥、公钥、身份证书等)从PFX文件导入到JKS文件,以便在Java密钥库(Java Key Store,JKS)中使用它来安装WebLogic Server SSL。有时服务器证书是PFX格式的,要在WebLogic Server中利用相同的证书,我们需要将其证书导出到JKS文件库。
  2. 通过Java客户端调用双向SSL认证的web服务,需要PEM格式的客户端证书。同样地,通过Java客户端调用双向SSL认证的servlet也需要PEM格式的客户端证书。

  现在,让我们来看看如何执行这些转换。

要求

  要执行以上任务,我们必须先设置以下项目:

  • 经过域配置的WebLogic Server版本8.1或9.1。
  • 安装的OpenSSL(www.openssl.org)。
  • 可用的Java keytool(JDK中随附)。
  • PFX格式的源证书。
  • 文本编辑器。

将PFX私钥和证书导入到JKS

  在本节中,我们将会看到如何从PFX文件导出服务器的私钥、公钥、身份证书和CA证书,并将这些组件导入到JKS文件,以便在WebLogic Server中使用它来安装SSL。要在WebLogic Server中安装SSL,需要两个JKS文件库:一个称为信任密钥库(Trust Key Store),另一个称为身份密钥库(Identity Key Store)。您需要执行以下三个步骤来完成该任务:

1. 将不同证书从PFX导出到PEM

  运行/bin文件夹的openssl二进制文件。它将启动OpenSSL命令提示符。执行以下命令:

    pkcs12 -in MYCERTS.pfx -out MYCERTS.pem -nodes

  这会将MYCERTS.pfx文件中的数据转换为PEM格式,并将转换结果放置在MYCERTS.pem文件中。得到的文件将具有按以下顺序排列的所有证书:

  • 私钥
  • 身份证书
  • 根证书
  • 中间证书

  注意,所有证书(私钥、身份证书、根证书和中间证书)都包装在某些头部中,这些头部是证书的一部分。

2. 创建信任Java密钥库(Trust Java Key Store,Trust JKS)

  现在您需要从得到的PEM文件中抽取根证书并使用它创建Trust JKS:

  1. 在文本编辑器中打开MYCERTS.pem文件,将根证书复制并粘贴到一个新文件中,该文件名为my_key_root.pem。由于根文件的issuer和subject头部必须相同,所以您可以容易地找到根文件。
  2. 使用Java密钥工具实用程序将以上my_key_root.pem文件导入到JKS文件:
keytool -import -trustcacerts -file
my_key_root.pem -alias my_key_root
-keystore my_key_trust.jks -storepass

  得到的JKS在WebLogic Server中可以用作信任密钥库(Trust Key Store)。

3. 创建身份Java密钥库(Identity Java Key Store)

  1. MYCERTS.pem文件中,复制私钥并将其粘贴到一个不同的文件中,该文件名为my_key_pk.pem。由于私钥包装在以下两个头部中,所以很容易识别私钥:
    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----
  2. MYCERTS.pem文件中,复制以下证书并将其粘贴到一个新的文件中,该文件名为my_key_crt.pem
    • 身份证书
    • 中间证书
    • 根证书

      注意,证书必须按照以上所列顺序排列。由于文件中必须具有显示身份信息的头部,如个人或组织的名称、地址等,所以可以容易地在MYCERTS.pem文件中查找身份证书。中间证书是MYCERTS.pem文件中的最后一个证书。

  3. 现在设置WebLogic环境并运行以下命令:
    java utils.ImportPrivateKey -keystore  -storepass
    -storetype JKS -keypass -alias
    -certfile my_key_crt.pem -keyfile my_key_pk.pem
    -keyfilepass

      这将创建一个可在WebLogic Server中使用的JKS文件。注意,您可以使用上面提及的utils.ImportPrivateKey命令将许多私钥导入到一个密钥库中。有关utils.ImportPrivateKey的详细信息,请参阅术语词汇表

    将PFX转换到双向SSL认证的PEM证书格式

      通过Java客户端调用双向SSL认证的web服务,需要Java客户端具有PEM格式的证书——并且它必须包含正在调用的用户的私钥。下面,我们将假设用户浏览器中已经安装了客户端证书。在这种情况下,用户可以按照以下详细步骤导出证书。

    1. 将客户端证书从浏览器中导出并保存在MYCERTS.pfx文件中。请按照以下给出的步骤执行操作,该步骤适用于Internet Explorer浏览器(在其他浏览器上也执行类似步骤):
      1. 转到Internet Explorer -> Tools -> Internet Options -> Content选项卡。

        使用带密钥库的PFX和PEM证书格式图-1

      2. 按Certificates按钮并转到Personal选项卡。

        使用带密钥库的PFX和PEM证书格式图-2

      3. 选择要导出的证书并按export按钮。点击“next”,然后选择“Yes, export the private key”单选按钮。按“next”并勾选“Include all certificates in the certificate path if possible”。

        使用带密钥库的PFX和PEM证书格式图-3

      4. 下一页面将询问您提供保护私钥的密码。输入密码之后,就可以将证书保存到文件中。
    2. 现在打开OpenSSL命令提示符并执行以下命令:
    openssl pkcs12 -in MYCERTS.pfx -out MYCERTS.pem -nodes

      这会将PFX格式转换到PEM格式。MYCERTS.pem将具有以下按以下顺序排列的所有证书:

    • 私钥
    • 身份证书
    • 根证书
    • 中间证书

        从MYCERTS.pem文件中,使用重新排序的证书(仅仅通过复制和粘贴)创建一个新文件(名为my_key_crt.pem)。顺序很重要,否则宿主服务器将无法识别证书:

    • 身份证书
    • 中间证书
    • 根证书
    • 私钥

      现在,Java客户端可以直接使用my_key_crt.pem来调用SSL认证的web服务。

    结束语

      本教程对如何执行以下两个任务进行了讲解:

    • 从PFX服务器证书文件导出私钥、身份证书、中间证书和根证书,然后将它们导入到可以在单向SSL配置的WebLogic Server中使用的JKS文件。如果用户想要利用WebLogic Server中现有的PFX格式证书,这非常有用。
    • 将现有的客户端证书从PFX格式转换到可以在双向SSL通信中被Java客户端使用的PEM格式。

    参考资料

      以下产品文档链接提供了有关在WebLogic Server上配置SSL的其他信息:

    • 说明如何为WebLogic Server配置密钥库的演示文稿

    术语词汇表

      OpenSSL:该工具包提供全球范围全强度加密技术的SSL和TLS协议的实现。它还提供了转换不同格式(即从PFX到PEM)证书的功能。

       Java keytool:这是密钥和证书管理工具。它还管理一个存储了私钥和验证相应公钥的与它们相关联的X.509证书链的密钥库(数据库)。它能够使用户使用数字签名来管理他们自己的公/私钥对,管理用来作自我验证的相关联的证书(用户对其他用户/或服务进行自我验证),或管理数据完整性和验证服务。

       根证书:在密码技术和计算机安全中,根证书是未经签署的公钥证书或自我签署的证书,它是公钥基础设施方案的一部分。

       身份证书:在加密技术中,公钥证书(或身份证书)是使用数字签名来约束带有身份信息(如个人或组织的名称、地址等)的公钥的证书。该证书可以用于验证属于个人的公钥。

       中间证书:中间证书是由受信根证书发布的从属证书,更确切地说是发布终端实体服务器证书。证书链从受信的根CA开始,通过中间证书,到发布给用户的SSL证书结束。这样的证书称为链接的根证书。

       私钥/公钥:使用私钥/公钥对编码可确保数据由一个密钥加密且只能由另一个密钥对解密。这两个密钥实质上是类似的,可以相互交换使用:一个密钥用于加密,另一个密钥对用于解密。密钥对基于素数和它们的位的长度,可确保在没有密钥对时无法解密消息。密钥对的窍门是保持一个密钥是秘密的(私钥),同时将另一个密钥(公钥)分发给其他人。然后任何人可以发送给您一个只有您可以解密的加密消息。

       WebLogic ImportPrivateKey:ImportPrivateKey实用程序用于将私钥加载到私钥库文件中。该实用程序与WebLogic服务器安装捆绑在一起,您需要设置执行该实用程序的域环境(Domain_Dir/setEnv)。有关更多信息,请访问文档

星期三, 九月 19, 2007

初识Java内部类

初识Java内部类(zt)

提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比。内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构。下面从以下几个方面来介绍:

  • 第一次见面

public interface Contents {
int value();
}

public interface Destination {
String readLabel();
}

public class Goods {
private class Content implements Contents {
private int i = 11;
public int value() {
return i;
}
}

protected class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() {
return label;
}
}

public Destination dest(String s) {
return new GDestination(s);
}
public Contents cont() {
return new Content();
}
}

class TestGoods {
public static void main(String[] args) {
Goods p = new Goods();
Contents c = p.cont();
Destination d = p.dest("Beijing");
}
}

在这个例子里类Content和GDestination被定义在了类Goods内部,并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里,直接用 Contents c和Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作,也即封装性。

同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下:

outerObject=new outerClass(Constructor Parameters);

outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,也就引出了我们下一个话题——

  • 非静态内部类对象有着指向其外部类对象的引用

对刚才的例子稍作修改:

public class Goods {

private valueRate=2;

private class Content implements Contents {
private int i = 11*valueRate;
public int value() {
return i;
}
}

protected class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() {
return label;
}
}

public Destination dest(String s) {
return new GDestination(s);
}
public Contents cont() {
return new Content();
}
}

修改的部分用蓝色显示了。在这里我们给Goods类增加了一个private成员变量valueRate,意义是货物的价值系数,在内部类Content的方法value()计算价值时把它乘上。我们发现,value()可以访问valueRate,这也是内部类的第二个好处——一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。

有人会问,如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用:

outerClass.this

有了它,我们就不怕这种屏蔽的情况了。

  • 静态内部类

和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了,Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上,当然从设计的角度以及以它一些细节来讲还有区别。

除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。

  • 局部内部类

是的,Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。

public class Goods1 {
public Destination dest(String s) {
class GDestination implements Destination {
private String label;
private GDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
return new GDestination(s);
}

public static void main(String[] args) {
Goods1 g= new Goods1();
Destination d = g.dest("Beijing");
}
}

上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。

下面有一个更怪的例子:

public class Goods2{
private void internalTracking(boolean b) {
if(b) {
class TrackingSlip {
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() { return id; }
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}

public void track() { internalTracking(true); }

public static void main(String[] args) {
Goods2 g= new Goods2();
g.track();
}
}

你不能在if之外创建这个内部类的对象,因为这已经超出了它的作用域。不过在编译的时候,内部类TrackingSlip和其他类一样同时被编译,只不过它由它自己的作用域,超出了这个范围就无效,除此之外它和其他内部类并没有区别。

  • 匿名内部类

java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的:

new interfacename(){......}; 或 new superclassname(){......};

下面接着前面继续举例子:

public class Goods3 {
public Contents cont(){
return new Contents(){
private int i = 11;
public int value() {
return i;
}
};
}
}

这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象,看上去的确十分简洁。

在java的事件处理的匿名适配器中,匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码:

frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});

有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:

  1. 如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为final。
  2. 将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。
  3. 在这个匿名内部类中使用初始化代码块。
  • 为什么需要内部类?

java内部类有什么好处?为什么需要内部类?

首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。

不过你可能要质疑,更改一下方法的不就行了吗?

的确,以此作为设计内部类的理由,实在没有说服力。

真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。

本文的目的只是向大家介绍一下内部类的概念以及使用方法,在后续文章里,将会针对本文中的内容举更多具体的例子,以及介绍如何使用内部类构建一个Applicaton Framework。

配置Tomcat 4使用SSL

1.Tomcat简介
Tomcat是Apache Jakarta的子项目之一,作为一个优秀的开源web应用服务器,全面支持jsp1.2以及servlet2.3规范。因其技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的web应用服务器。

2.SSL(Server Socket Layer)简介
在网络上信息在源-宿的传递过程中会经过其它的计算机。一般情况下,中间的计算机不会监听路过的信息。但在使用网上银行或者进行信用卡交易的时候有可能被监视,从而导致个人隐私的泄露。由于Internet和Intranet体系结构的原因,总有某些人能够读取并替换用户发出的信息。随着网上支付的不断发展,人们对信息安全的要求越来越高。因此Netscape公司提出了SSL协议,旨在达到在开放网络(Internet)上安全保密地传输信息的目的,这种协议在WEB上获得了广泛的应用。 之后IETF(www.ietf.org)对SSL作了标准化,即RFC2246,并将其称为TLS(Transport Layer Security),从技术上讲,TLS1.0与SSL3.0的差别非常微小。

3.SSL工作原理
SSL协议使用不对称加密技术实现会话双方之间信息的安全传递。可以实现信息传递的保密性、完整性,并且会话双方能鉴别对方身份。不同于常用的http协议,我们在与网站建立SSL安全连接时使用https协议,即采用https://ip:port/的方式来访问。
当我们与一个网站建立https连接时,我们的浏览器与Web Server之间要经过一个握手的过程来完成身份鉴定与密钥交换,从而建立安全连接。具体过程如下:
1.用户浏览器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送到服务器。
2.服务器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送给浏览器,同时发给浏览器的还有服务器的证书。如果配置服务器的SSL需要验证用户身份,还要发出请求要求浏览器提供用户证书。
3.客户端检查服务器证书,如果检查失败,提示不能建立SSL连接。如果成功,那么继续。
4.客户端浏览器为本次会话生成pre-master secret,并将其用服务器公钥加密后发送给服务器。
5.如果服务器要求鉴别客户身份,客户端还要再对另外一些数据签名后并将其与客户端证书一起发送给服务器。
6.如果服务器要求鉴别客户身份,则检查签署客户证书的CA是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的pre-master secret,并用它通过某些算法生成本次会话的master secret。
7.客户端与服务器均使用此master secret生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上,能够显著提高双方会话时的运算速度。
8.客户端通知服务器此后发送的消息都使用这个会话密钥进行加密。并通知服务器客户端已经完成本次SSL握手。
9.服务器通知客户端此后发送的消息都使用这个会话密钥进行加密。并通知客户端服务器已经完成本次SSL握手。
10.本次握手过程结束,会话已经建立。双方使用同一个会话密钥分别对发送以及接受的信息进行加、解密。

4.配置Tomcat 4.x 使用SSL
4.1 用到的软件包
・Tomcat 4.0.2
用途:Web Server。
下载:http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.3/bin/
・JSSE 1.0,2
用途:用来产生Tocmcat使用的秘钥对(keystore)。
下载: http://java.sun.com/products/jsse/
・Openssl 0.9.9.6
用途:用来产生CA证书、签名并生成IE可导入的PKCS#12格式私钥。
下载:http://www.openssl.org/
以上工具的安装过程可以参考自带的帮助,本文就不再详细描述了。
4.2 建立自己的CA
4.2.1 建立工作目录
mkdir ca
4.2.2 生成CA私钥以及自签名根证书
4.2.2.1 生成CA私钥
openssl genrsa -out ca\ca-key.pem 1024
4.2.2.2 生成待签名证书
openssl req -new -out ca\ca-req.csr -key ca\ca-key.pem
4.2.2.3 用CA私钥进行自签名
openssl x509 -req -in ca\ca-req.csr -out ca\ca-cert.pem -signkey ca\ca-key.pem -days 365
4.3 设置Tomcat 4.x
在本文中用符号"%JDK_HOME%"来表示JDK的安装位置,用符号"%TCAT_HOME%" 表示Tomcat的安装位置。
4.3.1建立工作目录
mkdir server
4.3.2 生成server端证书
4.3.2.1 生成KeyPair
%JDK_HOME%\bin\keytool -genkey -alias tomcat_server -validity 365 -keyalg RSA -keysize 1024 -keypass changeit -storepass changeit -dname "cn=localhost, ou=department, o=company, l=Beijing, st=Beijing, c=CN" -keystore server\server_keystore
4.3.2.2 生成待签名证书
%JDK_HOME%\bin\keytool -certreq -alias tomcat_server -sigalg MD5withRSA -file server\server.csr -keypass changeit -keystore server\server_keystore -storepass changeit
4.3.2.3 用CA私钥进行签名
openssl x509 -req -in server\server.csr -out server\server-cert.pem -CA ca\ca-cert.pem -CAkey ca\ca-key.pem -days 365
4.3.2.4 导入信任的CA根证书到JSSE的默认位置(%JDK_ROOT %/jre/security/cacerts)
%JDK_HOME%\bin\keytool -import -v -trustcacerts -storepass changeit -alias my_ca_root -file ca\ca-cert.pem -keystore %JDK_HOME%\jre\lib\security\cacerts
4.3.2.5 把CA签名后的server端证书导入keystore
%JDK_HOME%\bin\keytool -import -v -trustcacerts -storepass changeit -alias tomcat_server -file server\server-cert.pem -keystore server\server_keystore
4.3.2.6 查看server端证书
keytool -list -keystore %JDK_HOME%\jre\lib\security\cacerts
keytool -list -keystore server\server_keystore
4.3.3 修改server.xml使Tomcat支持SSL
首先找到以下内容,去掉对其的注释。然后参照红色部分修改。如果配置Tomcat不验证客户身份,可以设置clientAuth="false"。

然后把文件server\server_keystore复制到目录%TCAT_HOME%\conf\下。
4.4 在IE中安装个人证书
4.4.1 建立工作目录
mkdir client
4.4.2 生成client私钥并用CA私钥签名
4.4.2.1 生成client私钥
openssl genrsa -out client\client-key.pem 1024
4.4.2.2 生成待签名证书
openssl req -new -out client\client-req.csr -key client\client-key.pem
4.4.2.3 用CA私钥进行签名
openssl x509 -req -in client\client-req.csr -out client\client.crt -signkey client\client-key.pem -CA ca\ca-cert.pem -CAkey ca\ca-key.pem -CAcreateserial -days 365
4.4.2.4 生成client端的个人证书
因为JSSE1.0.2没有完全实现了对PKCS#12格式文件的操作(只能读取,不能输出),所以在这里需要用openssl制作client端的个人证书(包含私钥)。
openssl pkcs12 -export -clcerts -in client\client.crt -inkey client\client-key.pem -out client\client.p12
4.4.2.5 安装信任的根证书
把ca\ca-key.pem改名为ca\ca-key.cer,在client端的IE中使用"工具 ' Internet选项 ' 内容 ' 证书 ' 导入"把我们生成的CA根证书导入,使其成为用户信任的CA。
4.4.3 安装个人证书
把client.p12导入到client端的IE中作为个人证书,导入过程同4.4.2.5。
4.5 用IE浏览器使用SSL协议访问Tomcat
4.5.1 启动Tomcat 4.x
执行%TCAT_HOME%\bin\startup.bat启动Tomcat 4.x
4.5.2 用IE访问Tomcat 4.x
在IE浏览器的地址栏中输入https://localhost:8443,如果前面的操作都正确的话,应该可以看到Tomcat的欢迎页面。同时状态栏上的小锁处于闭合状态,表示您已经成功地与服务器建立了要求客户端验证的SSL安全连接。

5 结论
以上我们实现了为Tomcat 4.x配置要求客户端验证的SSL的全过程。对于其它类型的服务器,例如Apache,Netscape Enterprise Server, Websphere,Weblogic等,一般只是在服务器端保存证书的方式略有不同,但它们的原理都是类似的,配置时可以在本文中办法的基础上做出相应的调整。
参考资料
・Tomcat SSL Configuration HOW-TO
・SSL3.0规范
・Description of the Secure Sockets Layer (SSL) Handshake (Q257591)
・keytool - Key and Certificate Management Tool
・Openssl使用手册

Baidu面试题

先问了个分布式加锁问题存在的问题,如何改进
然后是统计内存中bit 1的个数,要效率高,这个居然没做出来
然后是一次可以走1、2、3个楼梯,总的方法数
最后相当于设计一个QQ的简单数据结构,最大可加500好友,但是平均只有50个
问怎么存放。。最后提示到说链表和数组折衷一下,就是想不到……
走楼梯的 假设n档楼梯, f(n) = f(n-1)+f(n-2)+f(n-3), 利用程序或者母函数推出来。
统计一个数int (32)位 ,x = x & (x-1),可以让x的bit中1的位数减1, 知道x等于0,可以利用循环计算出x的bit位中1的个数。

星期一, 九月 10, 2007

Talking To Consumers + Blog Mining

Does talking to consumers plus blog content mining equal a new effective way to conduct market research ... I think so ...Neville Hobson's picture

Submitted by Neville Hobson on Mon, 01/03/2005 - 10:36.

Financial Times:
"When Procter & Gamble is deciding whether to put its advertisements on television or elsewhere, it puts a call in to Nicosia, Cyprus. The same holds true for Nissan and dozens of other leading corporations and marketing-services agencies.

The calls are requests for help and go to Nicosia because the city is the home of Integration, a small consultancy that has gained prominence by taking on one of the biggest questions facing advertisers: how to pick the best medium for a particular marketing message."

This interesting report in the FT last month focuses on the work of Integration and its founder and CEO, Oscar Jamhouri, a former executive of the BBDO ad agency. It discusses in some length Jamhouri's approach to market research.

For example:

"For a measurement guru, Mr Jamhouri's methods are surprising. Rather than use the hard data of advertising and sales figures, he bases his findings on meetings with consumers. He tries to get round the limits of question-and-answer sessions by prodding them to behave as they would in a sales situation. Then he listens. [...] Based on this interaction, Integration rates the impact of each contact in a category - its "contact clout factor" - and produces a score, or "brand experience share", that advertisers can use to decide between media.

This kind of measurement will only grow in importance, Mr Jamhouri argues, because consumers are getting more difficult to reach through television advertising. A new, more furtive generation of consumers is emerging and the big task facing advertisers will be to find them, he says.

"Ninety per cent of the success of a brand (in the past) was built on the mass media," he says. "P&G was the king of mass media. They knew how to manage it and that made them a success." Now, "there has been an explosion of media and contact consumption and the challenge is where do we get these guys. How do we reach them? How do we engage?""

For the answer to Jamhouri's questions - How do we reach them? How do we engage? - take a look at the ideas contained in a report in the Wall Street Journal, also last month, reporting on how some companies are now paying close attention to blogs as part of their market research:

The Wall Street Journal:
"The growing popularity of blogs and other online forums has prompted companies to pay more attention to what is being said about them on the Internet, and has given rise to a new kind of market research aimed at finding useful information in the sea of online chatter."

The Journal quotes the (now well-known) case study of the Kryptonite bike lock fiasco and what can happen when a company doesn't pay attention to what its consumers are saying in a medium where news, good or bad, travels very fast.

Add these two things together and you have an effective market research method.

Neville Hobson is the author of the popular NevilleHobson.com blog which focuses on business communication and technology.

Neville is currentlly the VP of New Marketing at Crayon. Visit Neville Hobson's blog: NevilleHobson.com.

星期五, 九月 07, 2007

Goolge-f(n)=n

Consider a function which, for a given whole number n, returns the number of onesrequired when writing out all numbers between 0 and n.
For example, f(13)=6. Notice that f(1)=1. What is the next largest n such that f(n)=n?
phylips 于 Mon Mar 26 21:50:27 2007 提到:

给你往下扩展一下~~~~,发现f(10^n)与10^n之间怪异的增长关系
0~9里面有1
0~99里面有20
0~999里面有300
0~9999里面有4000
0~99999里面有50000
0~999999里面有600000
0~9999999里面有7000000
0~99999999里面有80000000
0~999999999里面有900000000
0~9999999999里面有10000000000,这时f(10^n)=10^n,刚好差不多相等
再往下就出现f(10^n)>10^n的情况,具体关系也可以表示出来
不知是否这样可以从某个值往后
满足f(n)>n,仅是一假设,未作证实......

harry 于 Mon Mar 26 23:14:22 2007 提到:

我给出来个f(n)的计算公式,

int doli(long int n)
{
if(n > 9)
{
long int k1,k2,k3,k4;
long int temp;
k1=int(log10(double(n)));
k2=int(pow(10.0,double(k1)));
k3=int(pow(10.0,double(k1)-1));
k4=n%k2;
if(n/k2 == 1)
{
temp=n/k2*k1*k3+k4+1+doli(k4);
}
if(n/k2 > 1)
{
temp=n/k2*k1*k3+k2+doli(k4);
}
return temp;
}
else
{
if(n == 0)
{
return 0;
}
else
return 1;
}

}
phylips 于 Thu Mar 29 19:38:35 2007 提到:

恩,如果是单纯写个f(n)函数,这个方法就够用了

但是如果要用来求f(n)=n,如果采用单纯的从1到n穷举好像还不如badtang那个更直接,
要利用这个f(n)的方法,就需要改进查找策略,xiaocui给了个思路

f(n)与n的增长率的确是有规律的
对于这个f(n)=n这个函数,始终认为是只有有限个解的
前面有个扩展kingger的关于f(n)与n增长关系的实例

f(10^10)=10^10+1
f(10^20)=2*(10^20)+1
......

f(10^100)=10*(10^100)+1
f(10^101)=10.1*(10^101)+1
观察f(10^100)--f(10^101)之间我们就会发现,不会存在f(n)=n的解了
因为f(10^100)=10*(10^100)+1=10^101+1,已经大于10^101了
同样的道理可以发现f(10^101)--f(10^102)也无解了...
所以从10^100开始已经是必然无解的了
另外我怀疑最大的f(n)=n的n值要远小于10^100,可能位于10^10附近

星期四, 九月 06, 2007

Data Miner?

星期一下午。已经清闲了一周。第一次开会。下午匆匆忙忙给笔记本加了1G内存:)(现在 的内存可比猪肉便宜)~,拿到了在网上订购的Understading the linux kernel,大汗淋漓地奔向西一,还是迟到了10+分钟。开会自然是新的课题任务安排。我的任务为是“华人力学三剑客”之一的Harvard Prof.Zhigang Suo在国内做一个镜像,并挖掘相关领域的知识和个性化数据,也就是所谓的"Data mining",不知道是不是挂了一个羊头呢。一直希望自己能从事比较Cool一点的工作,希望这次生活不要强奸了我。接下来我会专注于机器学习和数据挖掘,我相信老师的意愿和我的是有大大的不同,期待找到一个汇合点坚持自我理想。
实验室也慢慢地在对我们open(尽管很早就进了实验室),新装修的,所以里面没有什么“家具设备”,几张桌子几台电脑暂时开始我们的科研生活。对此还是比较满意的,互动空间暂时很大,没有课的日子比较自由,当然也有事务缠身的时候,泡实验室的日子也继续着。期许我的进步吧。Be an expert!Embarrassed