java常见面试题及解答(精华)


JAVA 常见面试题及解答(精华) 2009-05-20 14:47:25| 分类: 编程语言|字号 订阅 1)transient 和 volatile 是 java 关键字吗?(瞬联) 如果用 transient 声明一个实例变量,当对象存储时,它的值不需要维持。例如: class T { transient int a; //不需要维持 int b; //需要维持 } 这里,如果 T 类的一个对象写入一个持久的存储区域,a 的内容不被保存,但 b 的 将被保存。 volatile 修饰符告诉编译器被 volatile 修饰的变量可以被程序的其他部分改变。在多 线程程序中,有时两个或更多的线程共享一个相同的实例变量。考虑效率问题,每 个线程可以自己保存该共享变量的私有拷贝。实际的变量副本在不同的时候更新, 如当进入 synchronized 方法时。 用 strictfp 修饰类或方法,可以确保浮点运算(以 及所有切断)正如早期的 Java 版本那样准确。切断只影响某些操作的指数。当一 个类被 strictfp 修饰,所有的方法自动被 strictfp 修饰。 strictfp 的意思是 FP-strict,也就是说精确浮点的意思。在 Java 虚拟机进行浮点运算 时,如果没有指定 strictfp 关键字时,Java 的编译器以及运行环境在对浮点运算的 表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往 无法令你满意。而一旦使用了 strictfp 来声明一个类、接口或者方法时,那么所声 明的范围内 Java 的编译器以及运行环境会完全依照浮点规范 IEEE-754 来执行。因 此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果 不一致的话,那就请用关键字 strictfp。 你可以将一个类、接口以及方法声明为 strictfp,但是不允许对接口中的方法以及 构造函数声明 strictfp 关键字,例如下面的代码: strictfp interface A {} public strictfp class FpDemo1 { strictfp void f() {} } 2. 错误的使用方法 interface A { strictfp void f(); } public class FpDemo2 { strictfp FpDemo2() {} } 一旦使用了关键字 strictfp 来声明某个类、接口或者方法时,那么在这个关键字所 声明的范围内所有浮点运算都是精确的,符合 IEEE-754 规范 的。例如一个类被声明为 strictfp,那么该类中所有的方法都是 strictfp 的。 2)抽象类和接口有什么区别?(瞬联) 1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关 系。但是,一个类却可以实现多个 interface。 2.在 abstract class 中可以有自己的数据成员,也可以有非 abstarct 的成员方法,而 在 interface 中,只能够有静态的不能被修改的数据成员(也就是必须是 static final 的,不过在 interface 中一般不定义数据成员),所有的成员方法都是 abstract 的。 3.abstract class 和 interface 所反映出的设计理念不同。其实 abstract class 表示的是 "is-a"关系,interface 表示的是"like-a"关系。 4.实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。 接口中则不能有实现方法。 5.接口中定义的变量默认是 public static final 型,且必须给其初值,所以实现类中 不能重新定义,也不能改变其值。 6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋 值。 7.接口中的方法默认都是 public,abstract 类型的。 3)能说一下 java 的反射(reflection)机制吗?(瞬联) 开放性和原因连接(causally-connected)是反射系统的两大基本要素 4)在 java 中怎样实现多线程?(瞬联) extends Thread implement Runnable 方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代 码即可。下面是一个例子: public class MyThread extends Thread { int count= 1, number; public MyThread(int num) { number = num; System.out.println ("创建线程 " + number); } public void run() { while(true) { System.out.println ("线程 " + number + ":计数 " + count); if(++count== 6) return; } } public static void main(String args[]) { for(int i = 0;i 〈 5; i++) new MyThread(i+1).start(); } } 这种方法简单明了,符合大家的习惯,但是,它也有一个很大的缺点,那就是如果我们的类已经从一个类 继承(如小程序必须继承自 Applet 类),则无法再继承 Thread 类,这时如果我们又不想建立一个新的类,应 该怎么办呢? 我们不妨来探索一种新的方法:我们不创建 Thread 类的子类,而是直接使用它,那么我们只能将我们的 方法作为参数传递给 Thread 类的实例,有点类似回调函数。但是 Java 没有指针,我们只能传递一个包含这个 方法的类的实例。 那么如何限制这个类必须包含这一方法呢?当然是使用接口!(虽然抽象类也 可满足,但是需要继承,而我们之所以要采用这种新方法,不就是为了避免继承带 来的限制吗?) Java 提供了接口 java.lang.Runnable 来支持这种方法。 方法二:实现 Runnable 接口 Runnable 接口只有一个方法 run(),我们声明自己的类实现 Runnable 接口并提供这一方法,将我们的线程 代码写入其中,就完成了这一部分的任务。但是 Runnable 接口并没有任何对线程的支持,我们还必须创建 Thread 类的实例,这一点通过 Thread 类的构造函数 public Thread(Runnable target);来实现。下面是一个例子: public class MyThread implements Runnable { int count= 1, number; public MyThread(int num) { number = num; System.out.println("创建线程 " + number); } public void run() { while(true) { System.out.println ("线程 " + number + ":计数 " + count); if(++count== 6) return; } } public static void main(String args[]) { for(int i = 0; i 〈 5;i++) new Thread(new MyThread(i+1)).start(); } } 严格地说,创建 Thread 子类的实例也是可行的,但是必须注意的是,该子类必须没有覆盖 Thread 类 的 run 方法,否则该线程执行的将是子类的 run 方法,而不是我们用以实现 Runnable 接口的类的 run 方法,对 此大家不妨试验一下。 使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码,有利于封装,它的缺点在 于,我们只能使用一套代码,若想创建多个线程并使各个线程执行不同的代码,则仍必须额外创建类,如果这 样的话,在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。 综上所述,两种方法各有千秋,大家可以灵活运用。 下面让我们一起来研究一下多线程使用中的一些问题。 三、线程的四种状态 1. 新状态:线程已被创建但尚未执行(start() 尚未被调用)。 2. 可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它 执行。 3. 死亡状态:正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推 荐,前者会产生异常,后者是强制终止,不会释放锁。 4. 阻塞状态:线程不会被分配 CPU 时间,无法执行。 四、线程的优先级 线程的优先级代表该线程的重要程度,当有多个线程同时处于可执行状态并等待获得 CPU 时间时,线程 调度系统根据各个线程的优先级来决定给谁分配 CPU 时间,优先级高的线程有更大的机会获得 CPU 时间,优 先级低的线程也不是没有机会,只是机会要小一些罢了。 你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于 1(MIN_PRIORITY)和 10(MAX_PRIORITY)之间,缺省是 5(NORM_PRIORITY)。 5)你用过哪种设计模式?(瞬联,IBM,aspenTech) 设计:design 模式:pattern 框架:framework 创建模式,结构模式和行为模式 GoF 设计模式 A.创建模式 设计模式之 Factory(工厂模式) 使用工厂模式就象使用 new 一样频繁.2002/10/9 更新 设计模式之 Prototype(原型模式) 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 设计模式之 Builder 汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder 模式就 是将这两种情况分开进行。 设计模式之 Singleton(单态模式) 保证一个类只有一个实例,并提供一个访问它的全局访问点 2002/10/9 更新 B.结构模式 设计模式之 Facade 可扩展的使用 JDBC 针对不同的数据库编程,Facade 提供了一种灵活的实现. 设计模式之 Proxy 以 Jive 为例,剖析代理模式在用户级别授权机制上的应用 设计模式之 Adapter 使用类再生的两个方式:组合(new)和继承(extends),这个已经在"thinking in java"中提到过. 设计模式之 Composite 就是将类用树形结构组合成一个单位.你向别人介绍你是某单位,你是单位中的一个元素,别人和你做买卖, 相当于和单位做买卖。文章中还对 Jive 再进行了剖析。 设计模式之 Decorator Decorator 是个油漆工,给你的东东的外表刷上美丽的颜色. 设计模式之 Bridge 将"牛郎织女"分开(本应在一起,分开他们,形成两个接口),在他们之间搭建一个桥(动态的结合) 设计模式之 Flyweight 提供 Java 运行性能,降低小而大量重复的类的开销. C.行为模式 设计模式之 Template 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Memento 很简单一个模式,就是在内存中保留原来数据的拷贝. 设计模式之 Observer 介绍如何使用 Java API 提供的现成 Observer 设计模式之 Chain of Responsibility 各司其职的类串成一串,好象击鼓传花,当然如果自己能完成,就不要推委给下一个. 设计模式之 Command 什么是将行为封装,Command 是最好的说明. 设计模式之 State 状态是编程中经常碰到的实例,将状态对象化,设立状态变换器,便可在状态中轻松切换. 设计模式之 Strategy 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Mediator Mediator 很象十字路口的红绿灯,每个车辆只需和红绿灯交互就可以. 设计模式之 Interpreter 主要用来对语言的分析,应用机会不多. 设计模式之 Visitor 访问者在进行访问时,完成一系列实质性操作,而且还可以扩展. 设计模式之 Iterator 这个模式已经被整合入 Java 的 Collection.在大多数场合下无需自己制造一个 Iterator,只要将对象装入 Collection 中,直接使用 Iterator 进行对象遍历。 6)请说一下 MVC 架构(瞬联,IBM,aspenTech) Model:模型层 View:视图层 Controller:控制层 MVC (Modal View Controler)本来是存在于 Desktop 程序中的,M 是指数据模型,V 是指用户界面,C 则是控 制器。使用 MVC 的目的是将 M 和 V 的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一 批统计数据你可以分别用柱状图、饼图来表示。C 存在的目的则是确保 M 和 V 的同步,一旦 M 改变,V 应该 同步更新。 模型-视图-控制器(MVC)是 Xerox PARC 在八十年代为编程语言 Smalltalk-80 发明的一种软件设计模 式,至今已被广泛使用。最近几年被推荐为 Sun 公司 J2EE 平台的设计模式,并且受到越来越多的使 用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但 也有一些缺点。 MVC 如何工作 MVC 是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用 MVC 应用程序被分成三个核 心部件:模型、视图、控制器。它们各自处理自己的任务。 视图 视图是用户看到并与之交互的界面。对老式的 Web 应用程序来说,视图就是由 HTML 元素组成的界面,在新 式的 Web 应用程序中,HTML 依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括 Macromedia Flash 和象 XHTML,XML/XSL,WML 等一些标识语言和 Web services. 如何处理应用程序的界面变得越来越有挑战性。MVC 一个大的好处是它能为你的应用程序处理很多不同的视 图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只 是作为一种输出数据并允许用户操纵的方式。 模型 模型表示企业数据和业务规则。在 MVC 的三个部件中,模型拥有最多的处理任务。例如它可能用象 EJBs 和 ColdFusion Components 这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格 式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所 以减少了代码的重复性。 控制器 控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击 Web 页面中的超链接和发送 HTML 表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然 后用确定用哪个视图来显示模型处理返回的数据。 现在我们总结 MVC 的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模 型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层 呈现给用户。 为什么要使用 MVC 大部分 Web 应用程序都是用像 ASP,PHP,或者 CFML 这样的过程化语言来创建的。它们将像数据库查询 语句这样的数据层代码和像 HTML 这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分 离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC 从根本上强制性的将它们分 开。尽管构造 MVC 应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。 首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应 用程序。对此,其中一个解决之道是使用 MVC,无论你的用户想要 Flash 界面或是 WAP 界面;用一个模型 就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。 由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用 HTML 来 表示,但是它们也有可能要用 Macromedia Flash 和 WAP 来表示。模型也有状态管理和数据持久性处理的功 能,例如,基于会话的购物车和电子商务过程也能被 Flash 网站或者无线联网的应用程序所重用。 因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果 你想把你的数据库从 MySQL 移植到 Oracle,或者改变你的基于 RDBMS 数据源到 LDAP,只需改变你的模型 即可。一旦你正确的实现了模型,不管你的数据来自数据库或是 LDAP 服务器,视图将会正确的显示它们。 由于运用 MVC 的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想 你能构造良好的松偶合的构件。 对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这 样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求 选择模型进行处理,然后选择视图将处理结果显示给用户。 MVC 的缺点 MVC 的缺点是由于它没有明确的定义,所以完全理解 MVC 并不是很容易。使用 MVC 需要精心的计划,由于 它的内部原理比较复杂,所以需要花费一些时间去思考。 你将不得不花费相当可观的时间去考虑如何将 MVC 运用到你的应用程序,同时由于模型和视图要严格的分 离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经 过了测试,你就可以毫无顾忌的重用它们了。 根据我个人经验,由于我们将一个应用程序分成了三个部件,所以使用 MVC 同时也意味着你将要管理比以前 更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处 是不值一提。 MVC 并不适合小型甚至中等规模的应用程序,花费大量时间将 MVC 应用到规模并不是很大的应用程序通常 会得不偿失。 MVC 是一条创建软件的好途径 MVC 设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。 但是如果你要隔离模型、视图和控制器的构件,你可能需要重新思考你的应用程序,尤其是应用程序的构架方 面。如果你肯接受 MVC,并且有能力应付它所带来的额外的工作和复杂性,MVC 将会使你的软件在健壮性, 代码重用和结构方面上一个新的台阶。 7)如果类 a 继承类 b,实现接口 c,而类 b 和接口 c 中定义了同名变量,请问会 出现什么问题?(瞬联) 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 来明确(输出的是 1),而接 口的属性默认隐含为 public static final.所以可以通过 A.x 来明确(输出的是 0)。 下面的代码运行时会不会报错 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");"这里显示 有错。 8)请说一下 java 中为什么要引入内部类?还有匿名内部类?(瞬联,IBM) 9)请说一下 final,finally 和 finalize 的区别?(瞬联) final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继 承。 finally 是异常处理语句结构的一部分,表示总是执行。 finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此 方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。 10)请说一下 HTTP 请求的基本过程(IBM) 11)java 中存在内存泄漏问题吗?请举例说明?(IBM) 会 int i,i2; return (i-i2); //when i 为足够大的正数,i2 为足够大的负数。结果会造成 溢位,导致错误。 12)请说一下 java 中的内存回收机制所采用的算法(IBM,瞬联) 虽然垃圾回收关心着大部分的问题,包括内存管理,使得程序员的任务显得更加轻 松,但是程序员还是可能犯些错误导致内存泄漏问题。GC(垃圾回收)通过递归对 所有从“根”对象(堆栈中的对象,静态数据成员,JNI 句柄等等)继承下来的引用进 行工作,然后标记所有可以访问的活动着的对象。而这些对象变成了程序唯一能够 操纵的对象,其他的对象都被释放了。因为 GC 使得程序不能够访问那些被释放的 对象,所以这样做是安全的。 13)请说一下 System.gc()函数的作用。什么时候可以调用垃圾回收器?(瞬联) 垃圾回收函数,手动调用的. 当一个对象停止被活动声明所引用,它就变成了垃圾(garbage)可以被回收重新 使用 14)你做过的项目中采用了什么安全认证机制?(IBM) 15)Math.round()什么作用? Math.Round(3.44, 1) = 3.4 Math.Round(3.45, 1) = 3.4 Math.Round(3.46, 1) = 3.5 ----------------------------------------------- Math.Round(3.54, 1) = 3.5 Math.Round(3.55, 1) = 3.6 Math.Round(3.56, 1) = 3.6 ----------------------------------------------- Math.Round(3.64, 1) = 3.6 Math.Round(3.65, 1) = 3.6 Math.Round(3.66, 1) = 3.7 ----------------------------------------------- Math.Round(3.74, 1) = 3.7 Math.Round(3.75, 1) = 3.8 Math.Round(3.76, 1) = 3.8 这种舍入方法叫做银行家舍入(Banker'sRound),这就是已经规定下来的标准、Round 的标准、世界的 标准。 Round <> 四舍五入 16、设计 4 个线程,其中两个线程每次对 j 增加 1,另外两个线程对 j 每次减少 1。写出程序。 以下程序使用内部类实现线程,对 j 增减的时候没有考虑顺序问题。 package java_example150; public class TestThread3{ private int j; public static void main(String[] args){ TestThread3 t = new TestThread3(); Inc inc = t.new Inc(); Dec dec = t.new Dec(); for(int i=0;i<2;i++){ Thread ts = new Thread(inc); ts.start(); ts= new Thread(dec); ts.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<10;i++){ inc(); } } } class Dec implements Runnable{ public void run(){ for(int i=0;i<10;i++){ dec(); } } } } 17.CORBA 是什么?用途是什么? 答:CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture),由对 象管理组织 (Object Management Group,缩写为 OMG)标准化。它的组成是接口定义语言 (IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。 其目的为: 1. 用不同的程序设计语言书写 2. 在不同的进程中运行 3. 为不同的操作系统开发 18.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 把 abstractmethod 封锁起来呢? (同 理,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; } 答案: 正确。在 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 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。
还剩14页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

未了缘

贡献于2015-03-29

下载需要 6 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf