明航凯亚面试题

 


1. 下列代码的执行结果是什么:java

public class Test { public static void main(String[] args) { (new ThreadTest()).start(); } } class ThreadTest extends Thread{ @Override public void run() { System.out.println("In run"); yield(); System.out.println("leaving run."); } }

答案:In run 在leaving run以前被打印出来。设计模式

分析:Thread类的yield()方法的做用为线程让步,尝试释放当前线程对CPU资源的占用,并从新进入就绪状态。当其再次获取到CPU资源后会继续执行。数组

 


 

2. <jsp:forward>和HttpServletResponse的sendredirect()方法的主要区别描述正确的是:浏览器

答案为:forward执行在服务器端,而sendredirect在客户端服务器

分析:<jsp:forward> 的原理是HttpServletRequest的getRequestDispatcher的forward方法,为请求的转发,而sendredirect为页面的重定向。两者的完整区别为:  oracle

a.     重定向app

response.sendRedirect(你要跳转的路径)jsp

服务器告知给客户端,让客户端去请求你要跳转的路径。ide

一、          跳转前和跳转后的request对象不是同一个对象了;意味着跳转后不能从request中获取到跳转前的用户请求数据;post

二、          在客户端的浏览器地址栏上看到的地址是跳转的地址。

三、          能够跳转到项目外的地址;

四、          若是跳转的路径采用根路径的话,须要携带项目的上下文路径。

根路径:   /应用上下文/资源目录/文件名

问题:如何动态的获取到应用上下文路径?

            request.getContextPath()
五、          跳转后,若是客户端刷新页面,它只会刷新跳转后的页面

 b.     请求的转发

request.getRequestDispatcher(你要跳转的路径)

                .forward(request,response);

       服务器本身去请求跳转后的资源并执行,执行后将执行结果响应给客户端。

一、          跳转前和跳转后的request对象是同一个对象;意味着跳转后能够从request中获取到跳转前的用户请求数据;

二、          在客户端的浏览器地址栏上看到的地址是跳转的地址。

三、          不能够跳转到项目外的地址;

四、          若是跳转的路径采用根路径的话,不须要携带项目的上下文路径。

根路径:  /资源目录/文件名

五、   跳转后,若是客户端刷新页面,它会将跳转前和跳转后的页面都再执行一次。
六、   请求的转发,他能够跳转到WEB-INF下的页面。

3. 如下语句建立了几个对象
String a,b,c; a = "a"; b = "b"; a = a+b; StringBuffer d = new StringBuffer("abc"); d = d.append("567");

 



答案:这个题,说实话很诛心,很是的恶心,下面是分析

首先, 明确一下 建立对象 的具体含义. 按个人理解, 若是字符串是 字符常量, 那么这个字符串对象是在编译时候肯定好的, 它是存放在常量池中的, 所以就不算是建立了一个字符串对象, 而若是有 String b = new String("abc") 之类的操做, 那么能够认为是建立了字符串对象, 并与变量 b 关联.

根据上面的定义, 那么有: "a", "b", "abc", "567" 都是常量, 放在常量池中的, 所以就不算是建立对象了。

那么来看一下代码:
源码:

1: String a,b,c; 2: a = "a"; 3: b = "b"; 4: a = a+b; 5: StringBuffer d = new StringBuffer("abc"); 6: d = d.append("567");

为了方便起见, 我手动给每一行编号了.
再来看一下对应的字节码:

Code: stack=3, locals=5, args_size=1
     0: ldc           #2                  // String a
     2: astore_1 3: ldc           #3                  // String b
     5: astore_2 6: new           #4                  // class java/lang/StringBuilder
     9: dup 10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    13: aload_1 14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    17: aload_2 18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    24: astore_1 25: new           #8                  // class java/lang/StringBuffer
    28: dup 29: ldc           #9                  // String abc
    31: invokespecial #10                 // Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
    34: astore        4
    36: aload         4
    38: ldc           #11                 // String 567
    40: invokevirtual #12                 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
    43: astore        4
    45: return

由字节码能够看出, 源码的第四行 a = a+b 翻译为以下代码:

StringBuilder builder = new StringBuilder(); builder.append(a); builder.append(b); a = builder.toString();

那么这里就新建了一个对象 new StringBuilder(), 接着调用 builder.toString() 方法, 它源码以下:

@Override public String toString() { // Create a copy, don't share the array
    return new String(value, 0, count); }

因而 builder.toString() 方法建立了一个 String 对象, 所以目前咱们已经建立了 两个对象 了.

接着第五行 StringBuffer d = new StringBuffer("abc") 毫无疑问是 建立了对象 StringBuffer, 因而咱们就有 三个对象 了. 有一点须要注意的是 StringBuffer d 从始至终都没有调用 toString 方法, 所以就不会有多余的 String 建立出来.

总结:

  • "a": 字符串常量, 不算建立对象

  • "b": 字符串常量, 不算建立对象

  • builder 对象: 在执行 a = a+b 时建立.

  • "ab": 由 StringBuilder.toString() 建立.

  • "abc": 字符串常量, 不算建立对象

  • "567": 字符串常量, 不算建立对象

  • d: 经过 new StringBuffer("abc") 建立.

所以最终有三个对象建立了.

固然有的学者也将字符串常量理解为对象,这样的话总共就是七个对象被建立了

 


4. 在实现DAO设计模式时,下面哪一种模式常常被采用?
答案:Factory模式

5. 有以下的Servlet类
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class MyServlet extends HttpServlet { @Override public void init() throws ServletException { } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); out.print("hello"); } }

 

加入编译SErvlet要具有的环境都已经齐全,用彻底正确的命令编译此文件,描述正确的是:
答案:编译后,将MyServlet.class放在正确的位置,在浏览器中查看该servlet,会看到输出文字“hello”
分析:此servlet虽然没有doget和dopost,可是咱们分析HttpServlet中的doget方法源码可见:
 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

 

因而可知:servlet处理客户端的请求默认是经过service方法拦击全部的请求,并根据具体的客户端请求方式,调用对应的doXxx方法,而此题中service方法被重写,则客户端无论以何种method请求该servelt,均是执行重写后的service方法,而不会执行doXxx方法


6. 评估下面一组SQL语句:
CREATE TABLE DEPT (DEPTNO NUMBER(2),DNAME VARCHAR2(14),1oc VARCHAR2(13));
ROLLBACK; DESCRIBE DEPT
下面关于该组语句的描述哪一个是正确的?()

答案:A

分析: CREATE TABLE时不须要commit

describe 命令用于查看特定表的详细信息(oracle中)

 

7. 一个输入项的合法范围是0-100的整数,则其边界值为   -1,0,100,101

 

答案:D    

分析: 其实我以为B也有错,一个类实现了接口其实不必定非要实现接口的全部方法,只要该类为抽象类便可,让其子类再去实现方法;

         在java的重写中,遵循访问权限  重写前  <= 重写后的规则,而接口中全部的方法的访问修饰符都已是public最大了,因此实现接口不能够修改其访问权限;

  接口中定义变量,其实是定义的常量,在编译器编译时会自动追加: public static final 

 


答案:  有错

分析: 抽象方法不能有{}方法的实现体。


 

答案: 0次
分析:查看ArrayList的源码中的构造方法,在构造方法初始化的时候就已经建立大小为20的对象数组了。
 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }

可见,ArrayList在指定initialCapacity时是直接分配对象的数组空间为initialCapacity;

 

若是是 List list  = new ArrayList();

经过add方法插入20条记录的话,则遵循下面的法则:

ArrayList在没指定initialCapacity时会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间。
若是有20个数据须要添加,那么会分别在第一次的时候,将ArrayList的容量变为10;以后扩容会按照1.5倍增加。
也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15;当添加第16个数据时,继续扩容变为15 * 1.5 =22个。
相关文章
相关标签/搜索