`
meohao
  • 浏览: 94832 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

面试自己总结的一些java基础知识

阅读更多
1. k=k++; k++;的区别 ++问题的研究,可以结合我们写循环for条件中的i++
***************************************
int i=0;
i=i++;system.out.println(i);  >> 0
***************************************
int i=0;
i++;system.out.println(i);  >> 1
***************************************
int i=0;
i=i++ + ++i;                  //0+(1+1)=2
int j=0;
j = ++j + j++ + j++ + j++;    //1+(1)+(1+1)+(2+1)=7
system.out.println(i+" "+j);  >>2 7
***************************************
j = ++j + j++ + j++ + j++ + ++j + ++j + j++;   //1+(1)+(1+1)+(2+1)+(4+1)+(6)+6=24


2.在jdk安装之后,为什么可以在cmd命令行窗口中直接运行jsvs命令,而javac命令去报错,屏幕显示:
“javac”不是内部命令或外部命令,也不是可运行的程序或批处理文件。

java与javac是JDK在同一个子目录里面的两个文件,为什么可以直接运行java,而不能直接运行javac呢?
原来,Sun公司为了方便大家在安装完JDK后马上可以运行java类文件,在后台悄悄的地加入Path的搜索路径中,
因此可以直接运行java命令(但是看不到它到底是在哪里设置的,无论在用户的Path,还是itong的Path设置中
均找不到这个java存放的路径)。但是是Sun所做的到此为止,其他的JDK的命令,一概不管,需要由用户自己添
加到搜索路径当中。


3.x=x+1, x+=1, x++的效率哪个最高?
x=x+1最低,因为它的执行如下。
(1)读取右x的地址;
(2)x+1;
(3)读取左x的地址;
(4)将右值传给左边的x(编译器并不认为左右x的地址相同)。
x+=1其次,它的执行如下:
(1)读取右x的地址;
(2)x+1;
(3)将得到的值传给x(因为x的地址已经读出)。
x++最高,它的执行如下:
(1)读取右x的地址;
(2)x自增1。
答案:x++效率最高。

4.public class Test {
public static void main(String[] args) {
    byte b=2,c=3;
    byte f=b+c;                   // 此处报错    -> byte f=(byte)(b+c);
    System.out.println(f);
}
}
Java中涉及byte、short和char类型的运算操作首先会把这些值转换为int类型,然后对int类型值进行运算,最后得到int类型的结果。因此,
如果把两个byte类型的值相加,最后会得到一个int类型的结果,如果需要得到byte类型结果,必须将这个int类型的结果显式的转换为byte类型
byte f=(byte)(b+c);

如:short s=1;s=s+1;报错,可以改成以下代码,需要显式的强制转换
-> short s=1;
    s=(short)(s+1);


5.将整数转换为二进制、八进制、十六进制
    Integer i=34;               //这里用的是包装类,转换为二进制
    String s=i.toBinaryString(i);
    System.out.println(s);      >> 100010


6.从表单接收的数据都是字符串类型,如果在一个文本框中去捕获某一个人的年龄,就要用
Integer.parseInt(txtInputValue.getText());

7.static主函数中直接调用函数时要申明是静态的方法
public class inc {
public static void main(String[] args) {
String i = "123", s;
s = getStr(i);
}

private String getStr(String s) {  // -> private static String getStr(String s)
StringBuffer sb = new StringBuffer();
for (int j = s.length() - 1; j >= 0; j--) {
sb.append(s.charAt(j));
}
return sb.toString();
}

}


8.什么时候用assert?
assert是断言。断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true。如果表达式计算为false,
那么系统会报告一个assertionerror。它用于调试目的。
assert(a>0);//throw an Assertionerror if a<0;
答案:可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。
不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。
不过,既可以在公有方法中利断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。
分享到:
评论
4 楼 meohao 2010-08-28  
4. 模拟输入用户名和口令进行登录

本小节应该说是HTTP客户端编程中最常碰见的问题,很多网站的内容都只是对注册用户可见的,这种情况下就必须要求使用正确的用户名和口令登录成功后,方可浏览到想要的页面。因为HTTP协议是无状态的,也就是连接的有效期只限于当前请求,请求内容结束后连接就关闭了。在这种情况下为了保存用户的登录信息必须使用到Cookie机制。以JSP/Servlet为例,当浏览器请求一个JSP或者是Servlet的页面时,应用服务器会返回一个参数,名为jsessionid(因不同应用服务器而异),值是一个较长的唯一字符串的Cookie,这个字符串值也就是当前访问该站点的会话标识。浏览器在每访问该站点的其他页面时候都要带上jsessionid这样的Cookie信息,应用服务器根据读取这个会话标识来获取对应的会话信息。

对于需要用户登录的网站,一般在用户登录成功后会将用户资料保存在服务器的会话中,这样当访问到其他的页面时候,应用服务器根据浏览器送上的Cookie中读取当前请求对应的会话标识以获得对应的会话信息,然后就可以判断用户资料是否存在于会话信息中,如果存在则允许访问页面,否则跳转到登录页面中要求用户输入帐号和口令进行登录。这就是一般使用JSP开发网站在处理用户登录的比较通用的方法。

这样一来,对于HTTP的客户端来讲,如果要访问一个受保护的页面时就必须模拟浏览器所做的工作,首先就是请求登录页面,然后读取Cookie值;再次请求登录页面并加入登录页所需的每个参数;最后就是请求最终所需的页面。当然在除第一次请求外其他的请求都需要附带上 Cookie信息以便服务器能判断当前请求是否已经通过验证。说了这么多,可是如果你使用httpclient的话,你甚至连一行代码都无需增加,你只需要先传递登录信息执行登录过程,然后直接访问想要的页面,跟访问一个普通的页面没有任何区别,因为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实现了这样一个访问的过程。


/*

* Created on 2003-12-7 by Liudong

*/

package http.demo;

import org.apache.commons.httpclient.*;

import org.apache.commons.httpclient.cookie.*;

import org.apache.commons.httpclient.methods.*;

/**

* 用来演示登录表单的示例

* @author Liudong

*/

public class FormLoginDemo {

    static final String LOGON_SITE = "localhost";

    static final int    LOGON_PORT = 8080;

   

    public static void main(String[] args) throws Exception{

        HttpClient client = new HttpClient();

        client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);

      

       //模拟登录页面login.jsp->main.jsp

        PostMethod post = new PostMethod("/main.jsp");

        NameValuePair name = new NameValuePair("name", "ld");    

        NameValuePair pass = new NameValuePair("password", "ld");    

        post.setRequestBody(new NameValuePair[]{name,pass});

       int status = client.executeMethod(post);

        System.out.println(post.getResponseBodyAsString());

        post.releaseConnection();

      

       //查看cookie信息

        CookieSpec cookiespec = CookiePolicy.getDefaultSpec();

        Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies());

       if (cookies.length == 0) {

           System.out.println("None");   

       } else {

           for (int i = 0; i < cookies.length; i++) {

               System.out.println(cookies[i].toString());   

           }

       }

       //访问所需的页面main2.jsp

        GetMethod get = new GetMethod("/main2.jsp");

        client.executeMethod(get);

        System.out.println(get.getResponseBodyAsString());

        get.releaseConnection();

    }

}

5. 提交XML格式参数

提交XML格式的参数很简单,仅仅是一个提交时候的ContentType问题,下面的例子演示从文件文件中读取XML信息并提交给服务器的过程,该过程可以用来测试Web服务。

import java.io.File;

import java.io.FileInputStream;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.methods.EntityEnclosingMethod;

import org.apache.commons.httpclient.methods.PostMethod;

/**

* 用来演示提交XML格式数据的例子

*/

public class PostXMLClient {

    public static void main(String[] args) throws Exception {

        File input = new File(“test.xml”);

        PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”);

        // 设置请求的内容直接从文件中读取

        post.setRequestBody(new FileInputStream(input));

       

        if (input.length() < Integer.MAX_VALUE)

            post.setRequestContentLength(input.length());

        else            post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);

       

        // 指定请求内容的类型

        post.setRequestHeader("Content-type", "text/xml; charset=GBK");

       

        HttpClient httpclient = new HttpClient();

        int result = httpclient.executeMethod(post);

        System.out.println("Response status code: " + result);

        System.out.println("Response body: ");

        System.out.println(post.getResponseBodyAsString());

        post.releaseConnection();

    }

}

6. 通过HTTP上传文件

httpclient使用了单独的一个HttpMethod子类来处理文件的上传,这个类就是MultipartPostMethod,该类已经封装了文件上传的细节,我们要做的仅仅是告诉它我们要上传文件的全路径即可,下面的代码片段演示如何使用这个类。

MultipartPostMethod filePost = new MultipartPostMethod(targetURL);

filePost.addParameter("fileName", targetFilePath);

HttpClient client = new HttpClient();

//由于要上传的文件可能比较大,因此在此设置最大的连接超时时间

client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

int status = client.executeMethod(filePost);


上面代码中,targetFilePath即为要上传的文件所在的路径。

7. 访问启用认证的页面

我们经常会碰到这样的页面,当访问它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。这是HTTP的认证策略,httpclient支持三种认证方式包括:基本、摘要以及NTLM认证。其中基本认证最简单、通用但也最不安全;摘要认证是在HTTP 1.1中加入的认证方式,而NTLM则是微软公司定义的而不是通用的规范,最新版本的NTLM是比摘要认证还要安全的一种方式。

下面例子是从httpclient的CVS服务器中下载的,它简单演示如何访问一个认证保护的页面:


import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.UsernamePasswordCredentials;

import org.apache.commons.httpclient.methods.GetMethod;

public class BasicAuthenticationExample {

    public BasicAuthenticationExample() {

    }

    public static void main(String[] args) throws Exception {

        HttpClient client = new HttpClient();

        client.getState().setCredentials(

            "www.verisign.com",

            "realm",

            new UsernamePasswordCredentials("username", "password")

        );

        GetMethod get = new GetMethod("https://www.verisign.com/products/index.html");

        get.setDoAuthentication( true );

        int status = client.executeMethod( get );

        System.out.println(status+""+ get.getResponseBodyAsString());

        get.releaseConnection();

    }

}

8. 多线程模式下使用httpclient

多线程同时访问httpclient,例如同时从一个站点上下载多个文件。对于同一个HttpConnection 同一个时间只能有一个线程访问,为了保证多线程工作环境下不产生冲突,httpclient使用了一个多线程连接管理器的类:MultiThreadedHttpConnectionManager,要使用这个类很简单,只需要在构造HttpClient实例的时候传入即可,代码如下:

MultiThreadedHttpConnectionManager connectionManager =

   new MultiThreadedHttpConnectionManager();

HttpClient client = new HttpClient(connectionManager);

以后尽管访问client实例即可。

37.数组中有n个数据,要将它们顺序循环向后移动k位,即前面的元素向后移动k位,后面的元素则循环向前移k位,例如,0、1、2、3、4循环移动3位后为2、3、4、0、1。考虑到n会很大,不允许用2n以上 个空间来完成此题。
   
    这个问题其实就是将一个有n+m个元素的数组的前n个元素和后m个元素交换位置,我记得《编程珠玑》里面有一个很妙的算法,是这样的,先将前n个元素位置反转,再将后m个元素的位置反转,最后整个数组倒转,这样就完成了。例如:
有数组1,2,3,4,5,6,7,现在要将5,6,7移到数组最前面,即得到5,6,7,1,2,3,4。可以这样做:
第一步,反转前4个元素的位置:4,3,2,1,5,6,7
第二步,反转后3个元素的位置:4,3,2,1,7,6,5
第三步,反转整个数组      :5,6,7,1,2,3,4  
代码就不写了,因为非常简单。
很明显,时间复杂度O(n),空间效率O(1)。


前n-k位反转,后k位反转,之后整个数组反转就好。
数组可以看成向量ab,最终要变成ba

先把a翻转,就是1,2,3,4变成4,3,2,1那种翻转,得到aR
然后把b翻转,得到bR
然后再把整个数组翻转(aRbR)R,就能得到ba
编程珠玑里面介绍的

深拷贝和浅拷贝
所谓影子克隆是指 你得到的只是一个对象的引用
深度克隆 是指 你的得到的是一个 对象的副本

实现单线条表格
<html>
<head>
   <title>hehe</title>
<style type="text/css">
.td{border:1px #0066ff solid;}
.table{border-collapse:collapse;}
</style>


</head>
<body>
<table width="300" class="table">
        <tr align=center>
            <td class="td">1</td>
            <td class="td">2</td>
        </tr>
        <tr align=center>
            <td class="td">3</td>
            <td class="td">4</td>
        </tr>
</table>
</body>

W3C DOM和Javascript
这两者很容易混淆不清.DOM是面向HTML和XMl 文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。
JavaScript则是用于访问和处理DOM的语言。如果没有DOM,Javascript根本没有Web页面和构成页面元素的
概念。文档中的每个元素都是DOM的一部分,这就使得Javascript可以访问元素的属性和方法。

Ajax 中的Get和Post方法
唯一的区别就是,当使用Get发送请求时,查询串会追加到请求URL中,而使用Post方法时,则在调用XMLHttpRequest对象的send()方法时发送查询串。

为什么要把时间戳追加到目标URL?
在某些情况下,有些机器会把多个XMLHttpRequest请求的结果存在同一个URL中,如果每个请求的响应不同,就会带来不好的结果,把当前戳追加到URL的最后,就能确保URL的唯一性,


List和ArrayList的区别
1.
List是接口,List特性就是有序,会确保以一定的顺序保存元素.
ArrayList是它的实现类,是一个用数组实现的List.
Map是接口,Map特性就是根据一个对象查找对象.
HashMap是它的实现类,HashMap用hash表实现的Map,就是利用对象的hashcode(hashcode()是Object的方法)进行快速散列查找.(关于散列查找,可以参看<<数据结构>>)
2.
一般情况下,如果没有必要,推荐代码只同List,Map接口打交道.
比如:List list = new ArrayList();
这样做的原因是list就相当于是一个泛型的实现,如果想改变list的类型,只需要:
List list = new LinkedList();//LinkedList也是List的实现类,也是ArrayList的兄弟类
这样,就不需要修改其它代码,这就是接口编程的优雅之处.
另外的例子就是,在类的方法中,如下声明:
private void doMyAction(List list){}
这样这个方法能处理所有实现了List接口的类,一定程度上实现了泛型函数.
3.
如果开发的时候觉得ArrayList,HashMap的性能不能满足你的需要,可以通过实现List,Map(或者Collection)来定制你的自定义类.

五、编写 strcpy函数(10 分)
已知 strcpy函数的原型是
       char *strcpy(char *strDest, const char *strSrc);
       其中 strDest是目的字符串,strSrc 是源字符串。
(1)不调用 C++/C的字符串库函数,请编写函数 strcpy
char *strcpy(char *strDest, const char *strSrc);
{
    assert((strDest!=NULL) && (strSrc !=NULL));  // 2 分
    char *address = strDest;                   // 2 分
    while( (*strDest++ = * strSrc++) != ‘0’ )    // 2 分
       NULL ; 
    return address ;                          // 2 分
}

(2)strcpy 能把strSrc 的内容复制到strDest,为什么还要 char  * 类型的返
回值?
答: 为 了 实 现 链 式 表 达 式 。
// 2 分
例如       int length = strlen( strcpy( strDest, “hello world”) );

请写出 float  x 与“零值”比较的 if 语句。(4 分)
  标准答案示例:
const float EPSINON = 0.000001;
if ((x <= - EPSINON) && (x >= EPSINON)
不可将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或
“<=”此类形式。

   如下是错误的写法,不得分。
    if (x == 0.0)   
    if (x != 0.0)
3 楼 meohao 2010-08-28  
32.对字符串使用replaceAll()方法替换 * ? + \ | 等字符的时候会报以下异常 Dangling meta character '*' near index 0
这主要是因为这些符号在正则表达示中有相应意义。 只需将其将其改为
  •   或  \\*  即可。

  • 33.Arrays.sort();参数可以为任意基本类型的数值,对其进行排序。只有char[]后直接可以用syso输出排序后的数组。
    Arrays.asList();参数可以为任意基本类型的数值,可以将数组转化为list

    34.第二题:求输入数字长度:

    new String(src).length();

    逆序输出:

    new StringBuffer(src).reverse();


    35.equals()方法是Object类定义的一个方法,用来比较两个对象引用是否相等,和“==”表达式一样。
      所不同的是equals()方法可以在子类或者特定类中重写,例如String类就重写了该方法,使用String类的equals()方法可以比较两个String实例的内容是否相等。

    36.HttpClient
    引用 HttpClient入门教程java 2009-12-13 15:16:01 阅读1 评论0 字号:大中小





    一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面,比如从别人的网页中“偷”一些数据;利用某些站点提供的页面来完成某种功能,例如说我们想知道某个手机号码的归属地而我们自己又没有这样的数据,因此只好借助其他公司已有的网站来完成这个功能,这个时候我们需要向网页提交手机号码并从返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面,那我们的程序会很简单,本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一些服务授权的问题,很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的,而必须经过注册然后登录后方可使用提供服务的页面,这个时候就涉及到COOKIE问题的处理。我们知道目前流行的动态网页技术例如ASP、JSP无不是通过COOKIE来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面,就要求程序首先登录后再访问服务页面,这过程就需要自行处理cookie,想想当你用 java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情啊!况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的 “顽固”!再有如通过HTTP来上传文件呢?不需要头疼,这些问题有了“它”就很容易解决了!

    我们不可能列举所有可能的顽固,我们会针对几种最常见的问题进行处理。当然了,正如前面说到的,如果我们自己使用 java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先要介绍一下一个开放源码的项目,这个项目就是 Apache开源组织中的httpclient,它隶属于Jakarta的commons项目,目前的版本是2.0RC2。commons下本来已经有一个net的子项目,但是又把httpclient单独提出来,可见http服务器的访问绝非易事。

    Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,剩下的事情交给 httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进行分别介绍如何使用httpclient来解决它们,为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容,然后循序渐进解决掉前进中的所形侍狻?/font>

    1. 读取网页(HTTP/HTTPS)内容

    下面是我们给出的一个简单的例子用来访问某个页面

    /*

    * Created on 2003-12-14 by Liudong

    */

    package http.demo;

    import java.io.IOException;

    import org.apache.commons.httpclient.*;

    import org.apache.commons.httpclient.methods.*;

    /**

    * 最简单的HTTP客户端,用来演示通过GET或者POST方式访问某个页面

    * @author Liudong

    */

    public class SimpleClient {

        public static void main(String[] args) throws IOException

        {

            HttpClient client = new HttpClient();   

            //设置代理服务器地址和端口    

            //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);

            //使用GET方法,如果服务器需要通过HTTPS连接,那只需要将下面URL中的http换成https

            HttpMethod method = new GetMethod("http://java.sun.com");

            //使用POST方法

            //HttpMethod method = new PostMethod("http://java.sun.com");

            client.executeMethod(method);

            //打印服务器返回的状态

            System.out.println(method.getStatusLine());

            //打印返回的信息

            System.out.println(method.getResponseBodyAsString());

            //释放连接

            method.releaseConnection();

        }
    }

    在这个例子中首先创建一个HTTP客户端(HttpClient)的实例,然后选择提交的方法是GET或者 POST,最后在HttpClient实例上执行提交的方法,最后从所选择的提交方法中读取服务器反馈回来的结果。这就是使用HttpClient的基本流程。其实用一行代码也就可以搞定整个请求的过程,非常的简单!


    2. 以GET或者POST方式向网页提交参数

    其实前面一个最简单的示例中我们已经介绍了如何使用GET或者POST方式来请求一个页面,本小节与之不同的是多了提交时设定页面所需的参数,我们知道如果是GET的请求方式,那么所有参数都直接放到页面的URL后面用问号与页面地址隔开,每个参数用&隔开,例如:http://java.sun.com?name=liudong&mobile=123456,但是当使用POST方法时就会稍微有一点点麻烦。本小节的例子演示向如何查询手机号码所在的城市,代码如下:

    /*

    * Created on 2003-12-7 by Liudong

    */

    package http.demo;

    import java.io.IOException;

    import org.apache.commons.httpclient.*;

    import org.apache.commons.httpclient.methods.*;

    /**

    * 提交参数演示

    * 该程序连接到一个用于查询手机号码所属地的页面

    * 以便查询号码段1330227所在的省份以及城市

    * @author Liudong

    */

    public class SimpleHttpClient {

        public static void main(String[] args) throws IOException

        {

            HttpClient client = new HttpClient();

            client.getHostConfiguration().setHost("www.imobile.com.cn", 80, "http");

            HttpMethod method = getPostMethod();//使用POST方式提交数据

            client.executeMethod(method);

           //打印服务器返回的状态

            System.out.println(method.getStatusLine());

            //打印结果页面

            String response =

               new String(method.getResponseBodyAsString().getBytes("8859_1"));

           //打印返回的信息

            System.out.println(response);

            method.releaseConnection();

        }

        /**

         * 使用GET方式提交数据

         * @return

         */

        private static HttpMethod getGetMethod(){

            return new GetMethod("/simcard.php?simcard=1330227");

        }

        /**

         * 使用POST方式提交数据

         * @return

         */

        private static HttpMethod getPostMethod(){

            PostMethod post = new PostMethod("/simcard.php");

            NameValuePair simcard = new NameValuePair("simcard","1330227");

            post.setRequestBody(new NameValuePair[] { simcard});

            return post;

        }

    }

    在上面的例子中页面http://www.imobile.com.cn/simcard.php需要一个参数是simcard,这个参数值为手机号码段,即手机号码的前七位,服务器会返回提交的手机号码对应的省份、城市以及其他详细信息。GET的提交方法只需要在URL后加入参数信息,而POST则需要通过NameValuePair类来设置参数名称和它所对应的值

    3. 处理页面重定向

    在JSP/Servlet编程中response.sendRedirect方法就是使用HTTP协议中的重定向机制。它与JSP中的<jsp:forward …>的区别在于后者是在服务器中实现页面的跳转,也就是说应用容器加载了所要跳转的页面的内容并返回给客户端;而前者是返回一个状态码,这些状态码的可能值见下表,然后客户端读取需要跳转到的页面的URL并重新加载新的页面。就是这样一个过程,所以我们编程的时候就要通过 HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认需要进行页面跳转了,那么可以通过读取HTTP头中的location属性来获取新的地址。

    状态码
    对应HttpServletResponse的常量
    详细描述

    301
    SC_MOVED_PERMANENTLY
    页面已经永久移到另外一个新地址

    302
    SC_MOVED_TEMPORARILY
    页面暂时移动到另外一个新的地址

    303
    SC_SEE_OTHER
    客户端请求的地址必须通过另外的URL来访问

    307
    SC_TEMPORARY_REDIRECT
    同SC_MOVED_TEMPORARILY



    下面的代码片段演示如何处理页面的重定向

    client.executeMethod(post);

            System.out.println(post.getStatusLine().toString());

            post.releaseConnection();

           

            //检查是否重定向

            int statuscode = post.getStatusCode();

            if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||

                (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) ||

                (statuscode == HttpStatus.SC_SEE_OTHER) ||

    (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {

    //读取新的URL地址

                Header header = post.getResponseHeader("location");

                if (header != null) {

                    String newuri = header.getValue();

                    if ((newuri == null) || (newuri.equals("")))

                        newuri = "/";

                    GetMethod redirect = new GetMethod(newuri);

                    client.executeMethod(redirect);

                    System.out.println("Redirect:"+ redirect.getStatusLine().toString());

                    redirect.releaseConnection();

                } else

                    System.out.println("Invalid redirect");

            }

    我们可以自行编写两个JSP页面,其中一个页面用response.sendRedirect方法重定向到另外一个页面用来测试上面的例子。
    2 楼 meohao 2010-08-28  
    15.定义在类里面的变量会被赋予一个默认的值,布尔类型的默认初始值为false,而函数里面的变量只申明时是没有默认值的,相当于全局变量和
    局部变量的区别。

    16.假设任何异常处理已经被创建,创建RandomAccessFile类实例:
    RandomAccessFile raf=new RandomAccessFile("myfile.txt","rw");
    在Java的I/O结构中,RandomAccessFile是比较不寻常的类,它直接继承于Object,它并不属于Streams结构的一部分。

    17.需要读一个比较大的文本文件,这个文件里有很多字节的数据,那么读这类文件最合适:
    new BufferedReader( new InputStreamReader(new FileInputStream("file.name")));

    18.用Java Socket编程,读读服务器几个字符,再写入本地显示
    服务器端:
    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("Client send is "+line);

    out=new PrintWriter(socket.getOutputStream(),true);
    out.println("Your Meseage Received");
    out.close();
    in.close();
    socket.close();
    }
    } catch (IOException e) {
    out.print("wrong");
    }
    }
    public static void main(String[] args) throws IOException {
           new Server();
    }

    }
    客户端:
    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) throws IOException {
    new Client();
    }
    }

    29.如果一个数是2的阶次方数,那么它的二进制数的首位一般是1,后面接若干个0。比如8:就是1000,64:1000000,如果这个数减1后,再与该数
    做和(&)运算,则应该全为0(8与7,一个二进制是1000,一个二进制是111,它们做和运算后全为0)。所以(d-1)&d==0。

    30.如何实现java的序列化?
    解析:Java的"对象序列化"能将一个实现了serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,就能把这些byte数据
    恢复出来,并据此重新构建那个对象了。这一点甚至在跨网络的环境下也是如此,这就意味着序列化机制可以自动补偿操作系统之间的差异
    。也就是说,可以在windows机器上创建一个对象,序列化之后,再通过网络传到Unix机器上,然后再那里进行重建。不必担心在不同的平台
    上数据是怎样表示的,byte顺序怎样,或者别的什么细节。

    答案:序列化一个对象还是比较简单的,只要让它实现Serializable接口就行了(这是一个"标记接口"),没有任何方法,但是,当语言引入
    序列化概念之后,它的很多标准类库的类,包括ptimitive的wrapper类,所有的容器类,以及别的很多类,都会对应地发生改变,甚至连class
    对象都会被序列化。
    要想序列化对象,必须先创建一个OutpStream,然后把它嵌进ObjectOutputStream。这时,就能用writeObject()方法把对象写入OutputStream了,
    读的时候,得把InputStream嵌到ObjectInputStream里面,然后再调用readObject()方法。不过这样读出来的,只是一个Object的reference,因此
    在用之前,还得先下传。

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.Vector;


    class Room implements Serializable {
    }

    class Person implements Serializable {
    String name;
    Room preferredroom;

    public Person(String name, Room room) {
    this.name = name;
    this.preferredroom = room;
    }

    /**
    * public String toString()返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。
    * 结果应是一个简明但易于读懂。建议所有子类都重写此方法。 Object 类的 toString
    * 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、 at
    * 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于: getClass().getName() +
    * '@' + Integer.toHexString(hashCode()) 返回: 该对象的字符串表示形式。
    */

    public String toString() {
    return name + "[" + super.toString() + "]," + preferredroom + "\n";
    }
    }

    public class inc {
    public static void main(String[] args) {
    Vector<Person> p = new Vector<Person>();
    Room room = new Room();
    p.addElement(new Person("bobo", room));
    p.addElement(new Person("baba", room));
    p.addElement(new Person("meihao", room));
    System.out.println(p);

    try {
    ByteArrayOutputStream buf1 = new ByteArrayOutputStream();
    ObjectOutputStream o1 = new ObjectOutputStream(buf1);
    o1.writeObject(p);
    o1.writeObject(p);
              
    //写入另一个流中
    ByteArrayOutputStream buf2 = new ByteArrayOutputStream();
    ObjectOutputStream o2 = new ObjectOutputStream(buf2);
    o2.writeObject(p);

    ObjectInputStream in1 = new ObjectInputStream(
    new ByteArrayInputStream(buf1.toByteArray()));
    ObjectInputStream in2 = new ObjectInputStream(
    new ByteArrayInputStream(buf2.toByteArray()));

    Vector<Person> p1 = (Vector) in1.readObject();
    Vector<Person> p2 = (Vector) in1.readObject();
    Vector<Person> p3 = (Vector) in2.readObject();
    System.out.println("p1:" + p1);
    System.out.println("p2:" + p2);
    System.out.println("p3:" + p3);

    } catch (Exception e) {
    e.printStackTrace();
    }

    }

    }
    输出:
    [bobo[test.Person@150bd4d],test.Room@1bc4459
    , baba[test.Person@12b6651],test.Room@1bc4459
    , meihao[test.Person@4a5ab2],test.Room@1bc4459
    ]
    p1:[bobo[test.Person@1174b07],test.Room@3eca90
    , baba[test.Person@64dc11],test.Room@3eca90
    , meihao[test.Person@1ac1fe4],test.Room@3eca90
    ]
    p2:[bobo[test.Person@1174b07],test.Room@3eca90
    , baba[test.Person@64dc11],test.Room@3eca90
    , meihao[test.Person@1ac1fe4],test.Room@3eca90
    ]
    p3:[bobo[test.Person@161d36b],test.Room@17f1ba3
    , baba[test.Person@1ef8cf3],test.Room@17f1ba3
    , meihao[test.Person@ecd7e],test.Room@17f1ba3
    ]

    31.说明heap和stack的差别
    解析:
    栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
    int a=3;
    int b=3;
    首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有找到,
    就将3存放进来,然后将a指向3。接着处理"int b=3;",在创建完b的引用辩论后,因为
    在栈中已经有3这个值了,便将b直接指向3。这样就出现了a与b同时指向3的情况。
       这时,如果再令a=4,那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,
    并令a指向4,如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
        要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为在
    这种情况下,a的修改并不会影响到b,它是由编译器完成的,有利于节省空间。而一个对象引
    用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

       String是一个特殊的包装类数据,可以用一下两种形式来创建。
       String str=new String("abc");
       String str="abc";
       第一种是用new()来新建对象,它会存放于堆中。每调用一次就会创建一个新的对象。
    而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放
    "abc",如果没有,则将"abc"放进栈,并将str指向"abc",如果已经有"abc",则直接令str
    指向"abc"。
        比较类里面的数值石头相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象
    时,用"=="。下面用例子来说明。
    String str1="abc";
    String str2="abc";  栈中
    System.out.println(str1==str2);//true
    可以看出str1和str2是指向同一个对象的。

      String str1=new String("abc");
      String str1=new String("abc");   堆中
      system.out.println(str1==str2);//false
      system.out.println(str1.equals(str2));//true
     
      答案:
      heap是堆,stack是栈。
      栈和堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接设置栈和堆。
      Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new、newarray、anewarray等指令建立,
      他没不需要程序代码来显式地释放。堆是由垃圾回收来负责的。堆的优势是可以动态分配内存,Java的垃圾收
      集器会自动收走这些不再使用的数据。但是缺点是,由于要在运行时动态分配内存,存取速度较慢。
        栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但是缺点是,存在栈中的数据大小与生
    存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int short long byte float double boolean char)和对象句柄。

    1 楼 meohao 2010-08-28  
    7. main方法必须是public的,默认的是protect

    8.public static void main(String[] args) throws IOException {
    int i=23;
    //int i = -23;
    boolean s = isOdd(i);
    System.out.println(i);
    System.out.println(s);
    }

    private static boolean isOdd(int read) {
    return read % 2 ==1; //负奇数,求余之后是-1所以为负数
    //return read % 2 !=0;
    }


    9.System.out.println(2.00-1.10);  // -> 0.8999999999999999
      System.out.printf("%.2f%n",2.00-1.10);  // -> 0.90
      System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10"))); // -> 0.90
      System.out.println(new BigDecimal(2.00).subtract(new BigDecimal(1.10))); // -> 0.899999999999999911182158029987476766109466552734375


    10.public static void main(String[] args) throws IOException {
    //final long i=24*60*60*1000;
    //final long j=24*60*60;
    //System.out.println(i/j);   // -> 1000
    final long I=24*60*60*1000*1000;
    final long J=24*60*60*1000;
    System.out.println(I/J);     // -> 5

    final long I=24L*60*60*1000*1000;
    final long J=24L*60*60*1000;
    System.out.println(I/J);     // -> 1000

    }
    当操作数很大的时候提防其溢出,它是一个缄默杀手。

    除数和被除数看起来都是long类型的,但是long类型大到了可以很容易地保存这两个乘积而不产生溢出,但是结果打印的却是5,
    尽管计算的结果适合放入long中,并且空间还有富余,但是这个结果并不适合放入int中。
    这个计算完全是以int运算执行的,并且只有在运算完成之后,其结果才被提升到long
    ,而此时已经太迟了;计算已经溢出了,它返回的是一个小了200倍的数值,从int提升到long
    是一种拓宽原始类型的转换,它保留了(不正确的数值。)
    为什么计算会是以int运算来执行的呢?因为所有乘在一起的因子都是int数值。当
    你将另个int数值相乘时,你将得到另一个int数值。java不具有目标确定类型的特性,这是一种语言特性,
    其含义是指粗出结果的变了的类型会影响到计算所使用的类型。通过使用long常量来替代int常量
    作为每一个乘积的第一个因子。

    public static void main(String[] args) throws IOException {
               System.out.println(Long.toHexString(0x100000000L+0xcafebabe));  // -> cafebabe
               System.out.println(Long.toHexString(0x100000000L+0xcafebabeL));  // -> 1cafebabe
    }

    11. 两个数交换
    public static void main(String[] args) throws IOException {
               int x=1984;
               int y=2001;
               x^=y^=x^=y;    //  -> x=0  y=1984
              // y=(x^=(y^=x))^y;   // ->x=2001  y=1984
      // x=x^(y^=(x^=y));  //-> x=0  y=0
               System.out.println("x="+x+"  y=" +y);
    }
    x^=y^=x^=y 的执行
    x=x^y;
    y=y^x;
    x=x^y;


    x^y^x==y

    12. 选择的打印函数不一样
        public static void main(String[] args) throws IOException {
            char x='X';
            int i=0;
            System.out.println(true?x:0);  // -> X
            System.out.println(false?i:x);// -> 88
    }
    13.java有指针么?
       有些人认为指针的操作很困难,而且十分危险,所以一厢情愿的认为它没有好处。同时由于Java有如此好的口碑,所以应该很轻易地免除自己以前编程中的麻烦。
       其中不肯夹带有指针这样的"危险品"。然而准确的说,Java是有指针的,事实上,Java中每个对象(除基本数据类型外)的标识符都属于指针
       的一种,但它们的使用受到了严格的限制和防范,不仅编译器对它们有"戒心",运行期系统也不例外。或者从另一个角度说,Java有指针,但没有传统指针的麻烦
       。曾一度将这种指针叫做“句柄”,但可以把它想象成“安全指针”。
      
    14.所有的函数调用本质上都是值传递,也就是说函数的形参的值只是实参的一个副本,关键在于形参和实参是什么类型的(是基本类型还是对象
    句柄,因为如果形参是对象句柄,那么所传递的这个副本就是对象句柄的副本,而不是对象句柄所指向的对象的副本)。

    相关推荐

    Global site tag (gtag.js) - Google Analytics