您的位置:首页 > 职场人生

Java面试技术点

2017-06-10 11:50 183 查看
第一部分Java基础

1.Java面试题:什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。

Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

2. ”static”关键字是什么意思?一个private或者是static的方法?

static表示静态的意义,它可以修饰一个变量,一个方法,被其修饰的变量被称为类变量,被其修饰的方法成为类方法,其随着类的加载而被加载。

无法重写被private修饰的方法,因为被private修饰的父类方法在子类中是不可见的。

static修饰的方法是静态绑定的,而方法覆盖是为了实现多态,是动态绑定,所以static修饰的方法不需要被覆盖

3. 创建线程有几种不同的方式?你喜欢哪一种?为什么?

①继承Thread类(真正意义上的线程类),是Runnable接口的实现。

②实现Runnable接口,并重写里面的run方法。

③使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。

调用线程的start():启动此线程;

调用相应的run()方法 继承于Thread类的线程类,可以直接调用start方法启动线程(使用static也可以实现资源共享).一个线程(对象)只能够执行一次start(),而且不能通过Thread实现类对象的run()去启动一个线程。

实现Runnable接口的类需要再次用Thread类包装后才能调用start方法。(三个Thread对象包装一个类对象,就实现了资源共享)。

线程的使用的话,注意锁和同步的使用。(多线程访问共享资源容易出现线程安全问题)

一般情况下,常见的是第二种。

* Runnable接口有如下好处:

*①避免点继承的局限,一个类可以继承多个接口。

*②适合于资源的共享

4. 语句for(
;1 ;)有什么问题 它是什么意思

答:和while(1)相同。while(1)其中1代表一个常量表达式,他永远不会等于0。所以,循环会一直执行下去。除非你设置break等类似的跳出循环语句循环才会中止。

5.do……while和while……do有什么区别

6. System.gc()和Runtime.gc()会做什么事情?

调用 gc 方法暗示着 Java 虚拟机做了一些努力来回收未用对象,以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回时,虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。

调用 System.gc() 实际上等效于调用: Runtime.getRuntime().gc()

7. SSH框架的原理和优点

Struts工作原理

MVC即Model-View-Controller的缩写,是一种常用的设计模式。MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让视图层更富于变化。MVC的工作原理,如下图1所示:

Struts 是MVC的一种实现,它将 Servlet和 JSP 标记(属于 J2EE 规范)用作实现的一部分。Struts继承了MVC的各项特性,并根据J2EE的特点,做了相应的变化与扩展。Struts的工作原理,

视图:主要由JSP生成页面完成视图,Struts提供丰富的JSP 标签库: Html,Bean,Logic,Template等,这有利于分开表现逻辑和程序逻辑。

控制:在Struts中,承担MVC中Controller角色的是一个Servlet,叫ActionServlet。ActionServlet是一个通用的控制组件。这个控制组件提供了处理所有发送到Struts的HTTP请求的入口点。它截取和分发这些请求到相应的动作类(这些动作类都是Action类的子类)。另外控制组件也负责用相应的请求参数填充 Action From(通常称之为FromBean),并传给动作类(通常称之为ActionBean)。动作类实现核心商业逻辑,它可以访问java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件,后者生成视图。所有这些控制逻辑利用Struts-config.xml文件来配置。

模型:模型以一个或多个java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用Java Bean或EJB等。

流程:在Struts中,用户的请求一般以*.do作为请求服务名,所有的*.do请求均被指向ActionSevlet,ActionSevlet根据Struts-config.xml中的配置信息,将用户请求封装成一个指定名称的FormBean,并将此FormBean传至指定名称的ActionBean,由ActionBean完成相应的业务操作,如文件操作,数据库操作等。每一个*.do均有对应的FormBean名称和ActionBean名称,这些在Struts-config.xml中配置。

核心:Struts的核心是ActionSevlet,ActionSevlet的核心是Struts-config.xml。

Struts优缺点

优点:

1.开源软件,能更深入的了解其内部实现机制。

2.Taglib标记库,灵活动用,能大大提高开发效率。

3.页面导航使系统的脉络更加清晰。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时,这种优势体现得更加明显。

4. 提供Exception处理机制 .

5. 数据库链接池管理

6. Struts 的Action必需是thread-safe方式,它仅仅允许一个实例去处理所有的请求。所以action用到的所有的资源都必需统一同步,这个就引起了线程安全的问题。

缺点:

Taglib是Struts的一大优势,但对于初学者而言,却需要一个持续学习的过程,甚至还会打乱你网页编写的习惯,但是,当你习惯了它时,你会觉得它真的很棒。

Struts将MVC的Controller一分为三,在获得结构更加清晰的同时,也增加了系统的复杂度。

ActionForms使用不便、无法进行单元测试(StrutsTestCase只能用于集成)

Spring的原理和优点

Spring真正的精华是它的loc模式实现的BeanFactory和AOP,它自己在这个基础上延伸的功能有些画蛇添足。

Spring

它是一个开源的项目,而且目前非常活跃;它基于IoC(Inversion of Control,反向控制)和AOP的构架多层j2ee系统的框架,但它不强迫你必须在每一层 中必须使用Spring,因为它模块化的很好,允许你根据自己的需要选择使用它的某一个模块;它实现了很优雅的MVC,对不同的数据访问技术提供了统一的 接口,采用IoC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transcation Managment,等等

优点

a. Spring能有效地组织你的中间层对象,不管你是否选择使用了EJB。如果你仅仅使用了Struts或其他为J2EE的 API特制的framework,Spring致力于解决剩下的问题。

b. Spring能消除在许多工程中常见的对Singleton的过多使用。根据我的经验,这是一个很大的问题,它降低了系统的可测试性和面向对象的程度。

c. 通过一种在不同应用程序和项目间一致的方法来处理配置文件,Spring能消除各种各样自定义格式的属性文件的需要。曾经对某个类要寻找的是哪个魔法般的属性项或系统属性感到不解,为此不得不去读Javadoc甚至源编码?有了Spring,你仅仅需要看看类的JavaBean属性。Inversion of Control的使用(在下面讨论)帮助完成了这种简化。

d. 通过把对接口编程而不是对类编程的代价几乎减少到没有,Spring能够促进养成好的编程习惯。

e. Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。

f. 使用Spring构建的应用程序易于单元测试。

g. Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。

h. Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适用于许多web应用。例如,Spring能使用AOP提供声明性事务管理而不通过EJB容器,如果你仅仅需要与单个数据库打交道,甚至不需要一个JTA实现。

i. Spring为数据存取提供了一个一致的框架,不论是使用的是JDBC还是O/R mapping产品(如Hibernate)。

Spring确实使你能通过最简单可行的解决办法来解决你的问题。而这是有有很大价值的。

缺点:使用人数不多、jsp中要写很多代码、控制器过于灵活,缺少一个公用控制器

8.以下代码运行的结果是:

public class Person
{

private String name="Person";

int age=0;

}

public class Child extends Person{

public String grade;

public static void main(String[]
args) {

Person p=new Child();

System.out.println(p.name);

}

}

9.以下代码运行的结果是:father

public class Test extends Father{

private String name="test";

public static void main(String[]
args) {

Test test=new Test();

System.out.println(test.getName());

}

}

class Father{

private String name="father";

public String getName(){

return name;

}

}

10.以下代码运行的结果是:finally 语句块 和是:43

public class Demo
{

public int add(int a,int b){

try{

return a+b;

}catch(Exception
e){

System.out.println("catch语句块");

}finally{

System.out.println("finally
语句块");

}

return 0;

}



public static void main(String[]
args){

Demo demo=new Demo();

System.out.println("和是:"+demo.add(9,34));

}

}11.java单例模式的几种写法

第一种(懒汉,线程不安全):

1 public class Singleton {

2 private static Singleton instance;

3 private Singleton (){}

4 public static Singleton getInstance() {

5 if (instance == null) {

6 instance = new Singleton();

7 }

8 return instance;

9 }

10 }

这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。

第二种(懒汉,线程安全):

1 public class Singleton {

2 private static Singleton instance;

3 private Singleton (){}

4 public static synchronized Singleton getInstance() {

5 if (instance == null) {

6 instance = new Singleton();

7 }

8 return instance;

9 }

10 }

11

这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。

第三种(饿汉):

1 public class Singleton {

2 private static Singleton instance = new Singleton();

3 private Singleton (){}

4 public static Singleton getInstance() {

5 return instance;

6 }

7 }

8

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy
loading的效果。

第四种(饿汉,变种):

1 public class Singleton {

2 private Singleton instance = null;

3 static {

4 instance = new Singleton();

5 }

6 private Singleton (){}

7 public static Singleton getInstance() {

8 return this.instance;

9 }

10 }

11

表面上看起来差别挺大,其实更第三种方式差不多,都是在类初始化即实例化instance。

第五种(静态内部类):

1 public class Singleton {

2 private static class SingletonHolder {

3 private static final Singleton INSTANCE = new Singleton();

4 }

5 private Singleton (){}

6 public static final Singleton getInstance() {

7 return SingletonHolder.INSTANCE;

8 }

9 }

10

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy
loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。

第六种(枚举):

1 public enum Singleton {

2 INSTANCE;

3 public void whateverMethod() {

4 }

5 }

6

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。

第七种(双重校验锁):

1 public class Singleton {

2 private volatile static Singleton singleton;

3 private Singleton (){}

4 public static Singleton getSingleton() {

5 if (singleton == null) {

6 synchronized (Singleton.class) {

7 if (singleton == null) {

8 singleton = new Singleton();

9 }

10 }

11 }

12 return singleton;

13 }

14 }

15

这个是第二种方式的升级版,俗称双重检查锁定,详细介绍请查看:http://www.ibm.com/developerworks/cn/java/j-dcl.html

在JDK1.5之后,双重检查锁定才能够正常达到单例效果。

总结

有两个问题需要注意:

1、如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类 装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。

2、如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。

对第一个问题修复的办法是:

1 private static Class getClass(String classname)

2 throws
ClassNotFoundException {

3 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

4

5 if(classLoader == null)

6 classLoader = Singleton.class.getClassLoader();

7

8 return (classLoader.loadClass(classname));

9 }

10 }

11

对第二个问题修复的办法是:

1 public class Singleton implements java.io.Serializable {

2 public static Singleton INSTANCE = new Singleton();

3

4 protected Singleton() {

5

6 }

7 private Object readResolve() {

8 return INSTANCE;

9 }

10 }

11

对我来说,我比较喜欢第三种和第五种方式,简单易懂,而且在JVM层实现了线程安全(如果不是多个类加载器环境),一般的情况下,我会使用第三种方式,只有在要明确实现lazy loading效果时才会使用第五种方式,另外,如果涉及到反序列化创建对象时我会试着使用枚举的方式来实现单例,不过,我一直会保证我的程序是线程安全的,而且我永远不会使用第一种和第二种方式,如果有其他特殊的需求,我可能会使用第七种方式,毕竟,JDK1.5已经没有双重检查锁定的问题了。

第二部分:综合能力

1. 你用过什么支撑软件?作用是什么?

2.使用哪些工具进行版本控制?(1分),谈谈其作用?

svn,git,cvs

面试中SVN管理知识点全面剖析

本文和大家学习一下SVN管理问题,SVN工作模型,分支的概念和版本库布局等内容,希望通过本文的学习,你对SVN管理有更加深刻的认识。

本节讲解一下SVN管理问题,在学习SVN的过程中,你可能会遇到SVN管理问题,只有掌握了SVN管理你才能够对SVN运用自如,欢迎大家一起来学习SVN管理。下面我们来看一下具体介绍。

一.SVN的工作模型:Subversion缺省使用复制-修改-合并模型

实际上是文件共享的问题,目前有两种策略:

A.锁定-修改-解锁模型有一点问题就是限制太多,经常会成为用户的障碍:

锁定可能导致管理问题。有时候Harry会锁住文件然后忘了此事,这就是说Sally一直等待解锁来编辑这些文件,她在这里僵住了。然后Harry去旅行了,现在Sally只好去找管理员放开锁,这种情况会导致不必要的耽搁和时间浪费。

锁定可能导致不必要的线性化开发。如果Harry编辑一个文件的开始,Sally想编辑同一个文件的结尾,这种修改不会冲突,设想修改可以正确的合并到一起,他们可以轻松的并行工作而没有太多的坏处,没有必要让他们轮流工作。

锁定可能导致错误的安全状态。假设Harry锁定和编辑一个文件A??Sally锁定并编辑文件B,如果A和B互相依赖,这种变化是必须同时作的,这样A和B不能正确的工作了,锁定机制对防止此类问题将无能为力—从而产生了一种处于安全状态的假相。很容易想象Harry和Sally都以为自己锁住了文件,而且从一个安全,孤立的情况开始工作,因而没有尽早发现他们不匹配的修改。

B.复制-修改-合并(CVS,SVN采用)

在这种模型里,每一个客户读取项目版本库建立一个私有工作副本—版本库中文件和目录的本地映射。用户并行工作,修改各自的工作副本,最终,各个私有的复制合并在一起,成为最终的版本,这种系统通常可以辅助合并操作,但是最终要靠人工去确定正误。

二。分支的概念

我们再来看一下SVN管理中分支的概念。版本控制系统的一个特性是能够把各种修改分离出来放在开发品的一个分割线上。这条线被称为分支。分支经常被用来试验新的特性,而不会对开发有编译错误的干扰。当新的特性足够稳定之后,开发品的分支就可以混合回主分支里(主干线).

版本控制系统的另一个特性是能够标记特殊的版本(例如某个发布版本),所以你可以在任何时候重新建立一个特定的构件和环境。这个过程被称作标记。

分支中最重要的概念就是独立于主干进行开发,在合并前,不同分支提交的代码互相不可见,互不干扰。但是主干持有所有分支的版本记录,因此主干可以合并分支。比较适用不同团队独立开发各自模块。另外在分支合并的时候需要做回归测试

三。版本库的布局

SVN管理中版本库的布局情况,svn文档是有推荐的目录结构,适用大多数情况:)当然理解了分支的概念,心中有剑也无需受此限制。

1. Therearesomestandard,recommendedwaystoorganizearepository

2. .Mostpeoplecreateatrunkdirectorytoholdthe“mainline”ofdevelopment,abranchesdirectorytocontainbranchcopies

3. ,andatagsdirectorytocontaintagcopies.Ifarepositoryholdsonlyoneproject

4. ,thenoftenpeoplecreatethesetop-leveldirectories:

如果一个版本库包含多个项目,人们通常按分支来安排布局:

大致用法如下:

traceview项目有两个开发人员wya,htyoung,同时htyoung做为项目管理员.

1.项目开始时htyoung在trunk创建了最初的文件这个作为mainline,然后用

svncptrunktags/first_init

svncptags/first_initbranches/wya

svncptags/first_initbranches/htyoung

创建工作文件夹,我们的开发人员wya,htyoung只在他们的开发文件夹branches/wya,branches/htyoung内工作,也就是commit.

2.一段时间后由项目管理员(htyoung),merge所有的修改到主线trunk上,同时htyoung和wya同主线同步.

3.再过一段时间我们发布0.1版本,为了有一个记录项目管理员(htyoung)用以下命令建了一个tags

svncptrunktags/Release0.1.0

4.这时又有一个开发人员JRD来了,项目管理员(htyoung)基于0.1给她建了一个工作分支svncptags/Release0.1.0branches/jrd

5.在我们发布完0.2时来了一个测试员TA,我们用以下命令为TA建一个工作文件夹

svncptrunktags/Release0.2.0

svncptags/Release0.2.0branches/ta。本节SVN管理问题讲解完毕。

Git是什么?

Git是目前世界上最先进的分布式版本控制系统(没有之一)。

Git有什么特点?简单来说就是:高端大气上档次!

那什么是版本控制系统?

如果你用Microsoft Word写过长篇大论,那你一定有这样的经历:

想删除一个段落,又怕将来想恢复找不回来怎么办?有办法,先把当前文件“另存为……”一个新的Word文件,再接着改,改到一定程度,再“另存为……”一个新文件,这样一直改下去,最后你的Word文档变成了这样:

过了一周,你想找回被删除的文字,但是已经记不清删除前保存在哪个文件里了,只好一个一个文件去找,真麻烦。

看着一堆乱七八糟的文件,想保留最新的一个,然后把其他的删掉,又怕哪天会用上,还不敢删,真郁闷。

更要命的是,有些部分需要你的财务同事帮助填写,于是你把文件Copy到U盘里给她(也可能通过Email发送一份给她),然后,你继续修改Word文件。一天后,同事再把Word文件传给你,此时,你必须想想,发给她之后到你收到她的文件期间,你作了哪些改动,得把你的改动和她的部分合并,真困难。

于是你想,如果有一个软件,不但能自动帮我记录每次文件的改动,还可以让同事协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里瞄一眼就可以,岂不是很方便?

这个软件用起来就应该像这个样子,能记录每次文件的改动:
版本
用户
说明
日期
1
张三
删除了软件服务条款5
7/12 10:38
2
张三
增加了License人数限制
7/12 18:09
3
李四
财务部门调整了合同金额
7/13 9:51
4
张三
延长了免费升级周期
7/14 15:17
这样,你就结束了手动管理多个“版本”的史前时代,进入到版本控制的20世纪

cvs

cvs 是一个版本控制系统。使用它,可以记录下你的源文件的历史。

例如,修改软件时可能会不知不觉混进一些 bug,而且可能过了很久你才会察觉到它们的存在。有了 cvs,你可以很容易地恢复旧版本,并从中看出到底是哪个修改导致了这个 bug。有时这是很有用的。

CVS服务器端对每个文件维护着一个修订号,每次对文件的更新,都会使得文件的修订号加1。在客户端中也对每个文件维护着一个修订号,CVS通过这两个修订号的关系,来进行Update,Commit和发现冲突等操作操作

2. 架构设计、概要设计、详细设计、顶层设计、总体设计、你是否了解过分别是什么?

Java架构设计

软件架构作为一个概念,体现在技术和业务两个方面。

从技术角度来说:软件架构随着技术的革新不断地更新其内容,软件架构建立于当前技术和一些基本原则的基础之上。  

先说一些基本原则:

分层原则:分层是为了降低软件深度复杂性而使用的关键思想,就像社会有了阶级一样,软件有了层次结构。

模块化原则:模块化是化解软件广度复杂的必然手段,模块化的目的就是让软件分工。

接口实现分离原则:随着软件模块化的不断深入改进,面向接口编程而不是面向实现编程可以让复杂度日趋增高的软件降低模块之间的耦合度,从而让各模块更轻松改进。从这个原则出发,软件也从微观进行了细致的规范化。

还有两个比较小但很重要的原则:

细节隐藏原则很显然把复杂问题简化,把难看的细节隐去,能让软件结构更清晰。其实这个原则使用很普遍,模式就很能体现这个原则的精神。

依赖倒置原则随着软件结构的进一步发展,层与层之间、模块与模块之间的依赖逐渐加深,而层、模块的动态可插拔要求不端增大。依赖倒置原则可看视
为接口实现分离原则的深化,根据此原则的精神,软件进入了工具时代。这个原则有点类似于知名的好莱坞法则:Don't call us, we'll call you。

以上这些原则奠定了我们的软件架构的价值指标。但软件架构毕竟是建立在当前技术之上的。而每一代技术都有架构模式。过去的不再说了,让我们现在就来看一下当前流行的技术,以及当前我们能采用的架构。

因为面向对象是当前最流行开发技术,且设计模式的大量使用使面向对象的走向成熟,而数据库是当前最有效的存储结构、web界面是当前最流行的用 户接口,所以当前最典型的三层次架构就架构在以上几项技术的基础之上,用数据库作存储层、用面向对象来实现业务层、用web来作为用户接口层。我们从三层
次架构谈起:

因为面向对象技术和数据库技术不适配,所以在标准三层次架构的基础上,我们增加了数据持久层,来管理O-R双向映射,但目前一直没有最理想的实 现技术。cmp和entity bean技术因为其实现复杂,功能前景有限,已接近被淘汰的边缘。JDO及hibernate作为o-r映射的后期之秀,尤其是hibernate,功能
相当完备。推荐作为持久层的首选。

在业务层,因为当前业务日趋负载,且变动频繁,所以我们必须有足够敏捷的技术来保证我们的适应变化的能力,在标准j2ee系统中session bean负责业务处理,且有不错的性能表现,但采用ejb系统对业务架构模式改变太大,且其复杂而昂贵,业务代码移植性差。而spring
作为一个bean配置的轻量级架构,漂亮的IOC模式实现,对业务架构影响小,所以推荐作为中间层业务框架。

在用户结构层,虽然servlet/jsp/jstl/javaBean 能够实现MVC架构,但终究过于粗糙。struts对MVC架构的实现就比较完美,Taperstry也极好地实现MVC架构,且采用基于事件的方式,非
常诱人,惜其不够成熟,我们仍旧推荐struts作为用户接口层基础架构。

因为业务层是三层次架构中最有决定意义的,所以让我们回到业务层细致地分析一下,在复杂的业务我们常常需要以下基础服务的一种或几种:事务一致 性服务acid(tool:jta/jts)、并发加锁服务concurrent&&lock、池化管理服务cache、访问控制服务(tool:jaas)、流程控制服务workflow、动态实现服务IOC,串行化消息服务(tool:jms)、负载平衡服务blance等。如果我们不采用重量级应用服务器(如weblogic,websphere,jboss等)及重量级组件(EJB),我们必须自己实现其中一些服务。虽然我们大多情况下,不需要所有这些服务,但实现起来却非易事。幸运的是我们有大量的开源实现代码,但采用开源代码却常常是件不轻松的事。

随着xml作为结构化信息传输和存储地位日渐重要,一些xml文档操作工具(DOM,Digester,SAX等)的使用愈发重要,而随着xml schema的工具的成熟,采用xml schema来设计xml文档格式,然后采用java
binding来生成java bean 会成为主要编程模式,而这又进一步使数据中心向xml转移,使在中小数据量上,愈发倾向于以xquery为查询语言的xml数据库。最近还有一个趋势, microsoft,ibm等纷纷大量开发中间软件如(microsoft office之infopath),可以直接从xml schema 生成 录入页面等非常实用的功能。还有web service 的广泛应用,都将对软件的架构有非常重大的影响。至于面向服务架构(SOA)前景如何,三层次架构什么时候走入历史,现在还很难定论。

aop的发展也会对软件架构有很深的影响,但在面向对象架构里,无论aspectJ还是jboss-aop抑是aspectWerks、 nanning都有其自身的严重问题:维护性很差,所以说它将很难走远。也许作为一个很好的思想,它将在web service里大展身手。

rdf,owl作为w3c语义模型的标志性的语言,也很难想象能在当前业务架构发挥太大影响。但如果真如它所声称那样,广泛地改变着信息的结构。那么对软件架构也会有深远影响。

.

探讨系统架构设计和概要设计

初步再来探讨下架构设计和概要设计的区别和边界问题。先谈下架构设计:

架构设计包括了功能性架构技术架构设计两个部分的内容,功能性架构解决业务流程和功能问题,而技术架构解决非功能性需求等问题。两种架构都包括了动态和静态两个方面的内容,对于功能性架构中动态部分为业务流程驱动全局用例,用例驱动的用例实现等;对于技术架构中动态部分为架构运行机制,而静态部分为框架,分层等方面的内容。

功能性架构包括了全局用例设计,这个本身是用例分析和设计的一个延续,而全局用例分析建议的思路仍然是业务流程,业务用例建模到系统用例建模的过程。全局用例分析清楚后可以开始考虑子系统和模块的划分,形成系统的功能架构图,当然在划分过程中一定要考虑到通过CRUD矩阵等分析方法来分析模块如何划分合理,如何保证模块本身高内聚和松耦合。

在全局用例分析完成后涉及到数据模型的设计,数据建模仍然从业务驱动,从最初的业务对象和单据入手,到最终的数据概念模型和逻辑模型等。架构设计中全局数据模型不一定覆盖所有的数据对象和数据表;但是核心的主数据,核心业务单据数据一定要覆盖到,模型到的层次到逻辑模型即可。如果用面向对象的分析方法,这里需要出的是UML建模中的概念模型和逻辑模型,体现核心对象和类,核心对象和类之间的关系。

将全局用例分析和数据模型建立融合在一起,可以看到这两者结合起来会形成一个系统完成的领域模型层。一直认为领域模型思路应该引入架构设计,只有领域模型才是真正关注功能性架构,而不用马上关注到具体的技术分层和技术实现。

前面两者做完后可以看到一个大系统被分解为了多个子系统或模块,那么接着要考虑的就是模块间的集成架构,分析完集成架构模块间的接口基本就出来了。接口设计应该是架构设计的另外一个核心内容。要明白架构设计一个重要作用就是架构设计完成后各个模块可以并行开始概要设计,详细设计和开发工作。只要大家都遵循架构设计约定的接口规则即可以了。

集成架构考虑完另外一个核心内容就是公共可复用组件的抽取和识别,包括了功能组件和技术组件,需要识别出来哪些是可复用的,如何进行复用。对于复用层次本身又包括了数据层复用,逻辑层组件复用,界面层UI组件的复用等。复用是架构价值体现的的另外一个关键点。

这些都做完后,接着一个步骤应该在架构设计阶段做的就是对架构输出成功进行模拟验证,前面完成了分解动作,必须通过模拟验证来看看后续分解内容能否很好的集成和组装。很多时候我们做架构设计的时候往往不做这块内容,导致架构设计一些内容变成空中楼阁,无法落地。

再回来看技术架构设计,首先谈下静态部分的内容。这里面就包括了软件开发的分层架构,开发框架等内容,包括开发规范约定,技术平台和语言的选择,使用的规约等都需要考虑。很多时候我们看到谈架构的时候说到的三层或多层架构,仅仅是完整架构设计里面很小的一部分内容。

除了分层架构外,接着考虑的就是各种非功能性需要,我们在架构上需要如何设计。这里面包括了事务,缓存,异常,日志,安全,性能,可用性,容错能力等。这些逐个点都要在架构设计中说清楚如何考虑,由于这些本身就属于一个应用系统中技术平台要考虑的内容,因此应该设计为较为公用的技术组件供上层的业务组件使用。要明白很多时候为何谈到AOP或可插拔架构,只有这样去考虑问题,才会考虑真正的功能性架构设计和功能实现和非功能性技术架构这块充分解耦,实现进一步的灵活装配。

再回到架构设计视图层面,还需要考虑的就是整个应用系统的部署架构,部署架构本身也包括了逻辑视图和物理视图,应用最终开发出来了如何进行部署,这涉及到了IT基础架构方面的细化,也需要考虑清楚。

概要设计

概要设计首先要明白的是根据架构设计的内容进一步对某个模块的设计进一步细化。架构设计在系统级,而概要设计在子系统或模块级。拿建筑来比喻,架构设计是把一个建筑的框架结构全部定清楚,包括地基要挖多深,核心框架和承重结构如何,每一层的结构图如何,应该分为几个大套间这些内容都应该定下来。每个大套间的水,电,气等管道接入点在哪里等。而概要设计要做的是拿着一个套间,来考虑这个套间内部该如何设计,如何划分功能区域,如何将水电气接入点进一步在房间内延伸,哪些地方需要进一步增加非承重的隔断等。

基于以上思路我们看到在架构设计的时候,除了很少部分的核心用例我们会谈到具体的用例实现完,大多数功能我们都不会谈到具体的用例实现层面。而到了概要设计则需要进一步的分解我这块模块究竟需要实现哪些功能点,具体的每个功能点究竟如何实现都必须要考虑到。

严格的概要设计,我们希望是到了概要设计的某个功能模块,模块所涉及到的核心的类全部会出来,类关系图全部会出来。数据库设计也进一步细化到该模块的数据库物理模型。对于用例进行用例实现分析,在实现分析过程中可以看到每个类核心的public方法全部会分析识别出来。

拿着架构设计的接口,概要设计也需要进一步细化,细化出接口具体的输入输出和使用方法,包括模块应该使用哪些外部接口,模块本身又提供哪些接口出去都必须细化清楚。做概要设计的时候一定要清楚当前做的这个模块在整个应用系统架构中的位置,和外部的集成和交互点。

概要设计不用到详细设计这么细化,包括类里面的私有方法,public方法的具体实现步骤和逻辑,伪代码等。但是我们要看到概要设计里面对于核心的业务逻辑必须要设计清楚如何实现,实现的机制和方法。很多时候我们到了概要设计画uml的时序图,很多时候一看没有任何意义,全是跨层的简单的交互和调用。这个应该在架构设计的架构运行机制说清楚即可。设计到多个业务类间的交互调用才是重点,一个简单的功能增删改查,完全没有必要画什么时序图。

其次架构设计中给出了各种安全,性能,缓存的设计。那么在概要设计中出来另外一个问题,即架构给出的各种实现方案和技术,我们在概要设计中如何选择,如何使用。不是所有功能都需要缓存,那就要说清楚哪些功能根据分析需要缓存,需要缓存哪些对象,缓存本身的时效性如何设置等问题。

概要设计作为我们要达到一个目的,就是不论是谁拿走概要设计来做,最终实现出来的功能模块不会走样,功能模块最终实现出来可能有性能,易用性等方面的问题,但是整个功能实现的大框架一定是定了的。

详细设计:暂无

顶层设计:暂无

Java中常见设计模式面试题 一、设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘
162b8
录模式、状态模式、访问者模式、中介者模式、解释器模式。

1.请列举出在JDK中几个常用的设计模式?

单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像Boolean.valueOf,观察者模式(Observer
pattern)被用于 Swing 和很多的事件监听中。装饰器设计模式(Decorator design pattern)被用于多个 Java IO 类中。

2. 什么是设计模式?你是否在你的代码里面使用过任何设计模式?

设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法。设计模式是代码可用性的延伸

3.Java 中什么叫单例设计模式?请用Java 写出线程安全的单例模式

单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。http://www.wendangxiazai.comng.Runtime是单例模式的经典例子。从
Java 5 开始你可以使用枚举(enum)来实现线程安全的单例。

4.说出常用的软件开发流程?你上一个项目是使用哪一种?

软件开发流程即软件设计思路和方法的一般过程,包括设计软件的功能和实现的算法和方法、软件的总体结构设计和模块设计、编程和调试、程序联调和测试以及编写、提交程序等一系列操作。

第一步:需求调研分析

软件开发流程

1相关系统分析员向用户初步了解需求,然后用word列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面。

2 系统分析员深入了解和分析需求,根据自己的经验和需求用WORD或相关的工具再做出一份文档系统的功能需求文档。这次的文档会清楚列出系统大致的大功能模块,大功能模块有哪些小功能模块,并且还列出相关的界面和界面功能。

3 系统分析员向用户再次确认需求。

第二步:概要设计

首先,开发者需要对软件系统进行概要设计,即系统设计。概要设计需要对软件系统的设计进行考虑,包括系统的基本处理流程、系统的组织结构、模块划分、功能分配、接口设计、运行设计、数据结构设计和出错处理设计等,为软件的详细设计提供基础。

第三步:详细设计

在概要设计的基础上,开发者需要进行软件系统的详细设计。在详细设计中,描述实 现具体模块所涉及到的主要算法、数据结构、类的层次结构及调用关系,需要说明软件系统各个层次中的每一个程序(每个模块或子程序)的设计考虑,以便进行编码和测试。应当保证软件的需求完全分配给整个软件。详细设计应当足够详细,能够根据详细设计报告进行编码。

第四步:编码

在软件编码阶段,开发者根据《软件系统详细设计报告》中对数据结构、算法分析和模块实现等方面的设计要求,开始具体的编写程序工作,分别实现各模块的功能,从而实现对目标系统的功能、性能、接口、界面等方面的要求。 

第五步:测试

测试编写好的系统。交给用户使用,用户使用后一个一个的确认每个功能。

第六步:软件交付准备

在软件测试证明软件达到要求后,软件开发者应向用户提交开发的目标安装程序、数据库的数据字典、《用户安装手册》、《用户使用指南》、需求报告、设计报告、测试报告等双方合同约定的产物。

《用户安装手册》应详细介绍安装软件对运行环境的要求、安装软件的定义和内容、在客户端服务器端及中间件的具体安装步骤、安装后的系统配置

《用户使用指南》应包括软件各项功能的使用流程、操作步骤、相应业务介绍、特殊提示和注意事项等方面的内容,在需要时还应举例说明。

第七步:验收

用户验收。

5.你熟悉的DBMS是哪几种?熟悉哪些版本?这些最新的DBMS最新的版本号是什么?

DBMS:数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,是用于建立、使用和维护数据库,简称DBMS。

著名数据库管理系统

  MS SQL

  SYBASE

  DB2

  ORACLE 11.2

  MySQL 5.6.24

  ACCESS

  VF

5. JNDI的用途是什么?tomcat服务器中在哪个文件配置JNDI?

Java术语

  英文全称是:Java Naming and Directory Interface

  术语解释:一组帮助做多个命名和目录服务接口的API。

  JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的;">命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI
SPI的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。集群JNDI实现了高可靠性JNDI[8],通过服务器的集群,保证了JNDI的
[u]负载平衡和错误恢复。在全局共享的方式下,集群中的一个应用服务器保证本地JNDI树的独立性,并拥有全局的JNDI树。每个应用服务器在把部署的服务对象绑定到自己本地的JNDI树的同时,还绑定到一个共享的全局JNDI树,实现全局JNDI和自身JNDI的联系。

  JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。

  JNDI可访问的现有的目录及服务有:

  DNS、XNam 、Novell目录服务、LDAP(Lightweight
Directory Access Protocol 轻型目录访问协议)、CORBA对象服务、文件系统、Windows
XP/2000/NT/Me/9x的注册表、RMI、DSML
v1&v2、NIS。

  JNDI优点:

  包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务;

  可以同时连接到多个命名或目录服务上;

  建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必指导对象或资源的物理ID。

  JNDI程序包:

  javax.naming:命名操作;

  javax.naming.directory:目录操作;

  javax.naming.event:在命名目录服务器中请求事件通知;

  javax.naming.ldap:提供LDAP支持;

  javax.naming.spi:允许动态插入不同实现。

  利用JNDI的命名与服务功能来满足企业级APIs对命名与服务的访问,诸如EJBs、JMS、JDBC 2.0以及IIOP上的RMI通过JNDI来使用CORBA的命名服务。

  JNDI与JDBC:

  JNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个纪录,同时返回数据库连接建立所必须的信息。

  代码示例:

  try{

  Context cntxt = new InitialContext();

  DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");

  }

  catch(NamingException ne){

  ...

  }

  JNDI与JMS:

  消息通信是软件组件或应用程序用来通信的一种方法。JMS就是一种允许应用程序创建、发送、接收、和读取消息的JAVA技术。

  代码示例:

  try{

  Properties env = new Properties();

  InitialContext inictxt = new InitialContext(env);

  TopicConnectionFactory connFactory = (TopicConnectionFactory)
inictxt.lookup("TTopicConnectionFactory");

  ...

  }

  catch(NamingException ne){

  ...

  }

  访问特定目录:举个例子,人是个对象,他有好几个属性,诸如这个人的姓名、电话号码、电子邮件地址、邮政编码等属性。通过getAttributes()方法

  Attribute attr =

  directory.getAttributes(personName).get("email");

  String email = (String)attr.get();

  通过使用JNDI让客户使用对象的名称或属性来查找对象:

  foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);

  通过使用JNDI来查找诸如打印机、数据库这样的对象,查找打印机的例子:

  Printer printer = (Printer)namespace.lookup(printerName);

  printer.print(document);

  浏览命名空间:

  NamingEnumeration list = namespace.list("o=Widget, c=US");

  while (list.hasMore()) {

  NameClassPair entry = (NameClassPair)list.next();

  display(entry.getName(), entry.getClassName());

  }

    常用的JNDI操作:

  常用的JNDI操作:

  void bind(String sName,Object object);――绑定:把名称同对象关联的过程

  void rebind(String sName,Object object);――重新绑定:用来把对象同一个已经存在的名称重新绑定

  void unbind(String sName);――释放:用来把对象从目录中释放出来

  void lookup(String sName,Object object);――查找:返回目录总的一个对象

  void rename(String sOldName,String sNewName);――重命名:用来修改对象名称绑定的名称

  NamingEnumeration listBinding(String sName);――清单:返回绑定在特定上下文中对象的清单列表

  NamingEnumeration list(String sName);

  代码示例:重新得到了名称、类名和绑定对象。

  NamingEnumeration namEnumList = ctxt.listBinding("cntxtName");

  ...

  while ( namEnumList.hasMore() ) {

  Binding bnd = (Binding) namEnumList.next();

  String sObjName = bnd.getName();

  String sClassName = bnd.getClassName();

  SomeObject objLocal = (SomeObject) bnd.getObject();[/u]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: