发布新日志

  • 日常和项目测试流程总结(淘宝)

    2012-04-27 23:10:07

    日常测试流程

    一般日常

    输入:日常需求用例(UC)

    输出:测试用例、沉淀;

    测试产品线负责人:分配测试资源;

    日常评审:日常开发工程师、日常测试工程师、PD、日常UC评审人(涉及到前端的需UED介入);

    Review测试用例:日常测试工程师、日常UC评审人。

    计划在周二或周四发布的日常,在周一或周三中午12点之前必须填写测试结果,“测试通过”或者“测试不通过”;

    需求确认找PD、开发,疑难bug处理找PD、测试产品线负责人、开发确认;

    预发布测试结果需要在4点之前反馈。

     大日常

    输入:大日常需求用例(UC)

     输出:测试计划、测试设计、测试用例、大日常测试沉淀、大日常需求质量结果。

    人:(这里指与一般日常不同的)

    制定测试计划:日常测试负责人;

    Review测试用例:日常测试负责人、日常测试工程师、日常UC评审人。

    紧急日常

    条件:产品出现bug且等级为P1级

    输入:流程管理平台发起紧急发布流程

    输出:产品发布通知

    人:

       提交紧急发布申请:发布申请人;

       确定备案并进行内部通知:技术支持;

       审批紧急发布需求:审批人;

       录入日常发布需求列表:开发线负责人(TL);

       修改代码:软件开发人员;

       发布:配置管理人员;

       监控发布需求:发布申请人和开发人员;

           跟踪完成进度:TL

    项目测试流程

    启动阶段

    进入标准:

    项目资源申请到位;

    PRD文档评审通过;

    技术方案通过评审。

    退出标准:

    项目正式立项邮件发出;

    CF项目空间、QC项目空间建立完成;

    在twork上创建项目空间。

    测试负责人建立项目QC空间阶段:

    输入:项目说明书。

    输出:邮件/旺旺通知项目组成员,QC项目空间访问方法。

    计划阶段

    进入标准:

    项目已批准,且已立项;

    项目必需的测试资源申请到位。

    退出标准:

    测试计划评审通过;

    项目计划评审通过。

    输出:

    1.需求功能分解表;

    2.《项目测试计划》;

    3.《子计划》;

    4.《项目测试计划》评审意见记录。

    注意:测试计划评审可以简要执行,由测试部门经理和PM审阅,邮件批准执行并纳入基线库。

    人:

               需求功能分解:项目测试负责人;注意:产出对应1

               项目测试计划:项目测试负责人、项目测试人员;注意:产出对应2、3

               计划评审:项目测试负责人、项目测试人员、项目经理。注意:产出对应4

     需求分析阶段

    进入标准:

    项目开发人员UC文档编写完成;

    界面原型已经产出。

    退出标准:

    UC预审发现的问题全部关闭;

    UC评审中发现的问题全部关闭。

    输出:

    1.UC预审问题录入QC文档bug库中;

    2.UC评审出的问题录入QC库。

    人:

    UC预审:项目测试人员   注意:产出对应1

    UC评审:PTM、PD/PM、UED、项目开发人员、项目测试人员、项目测试评审组   注意:产出对应2

    设计阶段

    进入标准:

    开发人员系统设计文档通过评审,测试人员即可进行测试设计文档编写

    退出标准:

    测试设计文档在测试内审中通过,且评审出的问题已修复;

    测试设计文档在测试外审中通过,且评审出的问题已修复。

    输出:

    1.《项目测试设计》;

    2.twork中产出业务框图。

    参与人员:

    系统设计:项目开发人员;

    系统设计评审:项目开发人员、项目测试负责人、项目测试人员、PD、PM。

     测试设计:项目测试人员

    用例开发阶段

    进入标准:

                   开发人员系统设计文档评审通过

    退出标准:

    测试用例内审通过,且评审出的问题已修复;

    测试用例外审通过,且评审出的问题已修复。

    输出:

    1.测试需求;

    2.测试用例(在QC中,叫测试计划);

    3.测试实验室 ;

    4.测试脚本 ;

                 5.测试用例评审问题记录表;

                 6.测试用例评审会议纪要。

    人:

       编写测试用例:项目测试人员;注意:产出对应1~4

       测试内审:PTM、项目测试评审组、项目测试人员;  注意:产出对应5

    测试外审:开发人员、测试人员、PD、PM、项目测试负责人;注意:产出对应6

    注意:测试内审可以简要执行,方法是:项目评审组线上review项目测试用例、测试设计,并以邮件的形式反馈给项目测试人员。

     测试执行阶段

    进入标准:

    测试用例评审通过,且评审出的问题已修复;

    开发人员在项目测试环境冒烟测试通过(测试实验室冒烟测试用例,开

    发人员执行全部为pass;

    项目经理提交《测试提交单》。

    退出标准:

    项目空间的所有1,2,3级bug关闭,且所有bug为最终状态;

    非closed的bug经需求方、PD、PM、测试人员、开发会审达成一致意见,并在项目质量评估报告中给出明确说明;

    项目质量评估报告被测试经理评审通过。

    输出:

    1.Bug报告;

    2.项目测试日报;

    3.项目质量评估报告。

    人:

             执行测试:项目测试人员、项目测试负责人; 注意:产出对应1~3

             项目质量评估:项目测试负责人、测试经理;注意:产出对应3

             预发布测试:项目测试人员。注意:产出对应1、2

    注意:主干环境回归测试特别说明:

    项目功能在日常环境回归

    与项目打分支期间关联的已发布日常的回归

    与项目打分支期间关联的已发布项目的应用回归

    与项目应用相关联的所有自动化脚本回归

    注意:在主干环境回归测试中是否执行P2、P3轮测试,要根据项目测试计划制定的策略进行裁剪。

    发布阶段

    进入标准:

    项目发布申请表中,发布审批人会签全部通过

    退出标准:

    发布过程完成,无重大(P1级)质量问题

    输出:

    线上bug;

    线上bug报告。

    人:

    发布验证:项目测试负责人、项目测试人员

    结项阶段

    进入标准:

     项目经理申请结项请求被批准

    退出标准:

    对应产品线测试用例入基线库;

    对应产品线MM图已更新;

    对应品线业务沉淀已完成;

    项目总结分享完成—项目总结报告.ppt。

    输出:

    基线测试用例;

    基线业务知识沉淀;

    基线MM框图;

    项目总结。

    人:

                项目总结:项目测试负责人、项目测试人员

    附加:

     有3个时间点需要关注
    1. 提交代码是 前3天15点
    2. 日常测试完成是 前1天12点
    3. 预发测试完成是 前1天16点

  • 如何进行前端bug定位(转至淘宝)

    2012-04-27 23:02:12

     

    首先必备工具Firefox debug工具

    可以考虑检查标签的排查工具 idea.exe

    如何区分页面的bug问题归属:前端or后端

    前端bug主要分为3个类别:HTML,CSS,Javascript三类问题

    给个最大的区别方式方法:

    1. 出现样式的问题基本都是CSS的bug
    2. 出现文本的问题基本都是html的bug
    3. 出现交互类的问题基本都是Javascript的bug

    现在以淘宝的前端人员工作为例进行相关bug定位的剖析

    判断前后台问题的区分方法:

    FF, 打开错误控制台

    1. 区分前后台交互:查看网络请求

    a)         Html中如果有链接,有相应的情况下,基本可以定位到是属于前端的问题

    b)         如果为空,或者有出现error错误信息,我们就可以定位到属于后台开发的问题

    1. TMS对应的VM模板,出现的一些截断控制,转换功能都属于前端的问题

    一、HTML

    最常见的HTML的问题—就是标签的问题了,最常见的排查和解决办法就是查看页面源代码,然后通过检查标签的工具,现在暂时提供idea.exe进行检查,有其他更好的工具再进行推荐。

    常见问题类别:

    1. 标签闭合—表象,页面中出现大范围的混乱,就是少了标签的情况,导致标签未闭合
    2. 标签浮出—例如鼠标移动到文本位置,浮出全名的这种浮出形式都属于标签浮出的问题
    3. 标签在不同的浏览器的一种解析方式的不同导致的前端bug例如如下结构

    该部分可以看做为一个大的框即是标签<a> 内嵌标题的标签<p>,里面再有这些个内容<ing>,那么在不同的浏览器中,可能ie和FF的解析会产生不同,假设IE解析为<a><p><ing></ing></a></p>的一种形式,但在FF下可能解析为

    <a><ing></ing></a>

    <p></p>

    的两行的形式从而导致前端在复古鞋/板鞋这块ing里面的格式产生混乱

    结构可看为:

     

    1. 页面定点的问题:最明显的前端功能,在于点击某个链接将页面位置定位到对应的位置

    a)         我们可以通过右键,查看元素的工具进行定位到毛点所定位到的位置,如果出现问题这种问题很直观,并且能通过这种方法直接定位到问题

    1. 页面的跳转,也属于html的问题,大家在出现点击未跳转或者跳转方式不正确的问题,直接可以定位到跳转属性的问题,找到对应的跳转对应的块提供给开发人员即可

    二、CSS,产生样式问题。例如:排版,布局,颜色,背景等

    css的bug主要分为:兼容型bug 、业务性bug 和 内容型bug

    1. 兼容型bug

    a)         表现:仅在少数几个浏览器上出现

    b)         原因:浏览器的解析不一致

    c)         解决:根据实际情况进行前端代码的通用性

    d)         类别:

    1. 脚本兼容型问题:在出现对应交互的问题就基本可以定位到脚本兼容型bug,例如DIV的显示和层结构。实际可以参考聚划算的几个商品鼠标移动到小图的时候,对应大图展示的功能。
    2. 页面样式兼容型问题:直接表象在样式上,都是基于框架的页面展示错误,很容易定位
    3. 业务性bug

    a)         表现:在所有浏览器下都有该问题

    b)         原因:对业务不熟悉

    c)         解决:根据需求进行修改达到业务要求

    该类型的定位,主要在和实现的要求不一致,最直接表现在页面的友好型,用户的可用性的bug,可以定位为该类型

     

    1. 内容型bug

    a)         表现: 前端自测正确,但在填入内容后,出现的错误,内容消失等

    b)         原因: 扩展性未考虑周全

    c)         解决: 进行overflow test

    输入内容的长度限制等功能可定位为内容型bug

     

    三、Javascript

    最直接的判断方法,刷新页面,出现滞后显示的一些模块基本都为脚本的输出块。该部分的一些问题可以参照兼容型bug中类别的脚本兼容型bug。

    1. 有产生交互类的问题,大多数都可以定位到是属于javascript产生的问题,该部分大多不会报错
    2. 有错误提示类的。页面左下方有出现javascript的错误提示;有弹出错误信息提示的bug;浏览器返回的一些错误弹出框都属于javascript的bug
  • 性能测试时,tomcat配置优化

    2011-12-28 17:38:11

    性能测试时,tomcat配置优化

    Tomcat连接数设置(建议的设置,可根据服务器的实际性能进行更改)

    tomcat配置文件server.xml中的配置中,和连接数相关的参数有:

    1 maxThreadsTomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。portal预置值300

    2 acceptCount指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。portal预置值50

    3 minSpareThreadsTomcat初始化时创建的线程数。portal预置值25

    4 maxSpareThreads一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。portal预置值75

    5 connnectionTimeout网络连接超时,默认值60000,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。portal预置值为30000毫秒。

    6 maxKeepAliveRequests保持请求数量,portal预置值100

    7  bufferSize输入流缓冲大小,portal预置值2048 bytes

    把端口的配置替换为如下的内容,可以提高tomcat的性能,并且同时关闭tomcat的打印信息。
    可以复制下面的代码进行粘贴后修改:

      <Connector port="80" maxHttpHeaderSize="8192" useBodyEncodingForURI="true"  
                   maxThreads="300" minSpareThreads="25" maxSpareThreads="75"  
                   enableLookups="false" redirectPort="8443" acceptCount="100"  
                   compression="off" compressionMinSize="2048"   
    compressableMimeType="text/html,text/xml,text/css,text/plain"  
                   connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>


    二,如果在性能测试中发现有tomcat内存溢出的错误,就需要加大虚拟内存了。

    Tomcat默认可以使用的内存为128MB,Windows,在文件/bin/catalina.batUnix下,在文件/bin/catalina.sh的前面,增加如下设置:JAVA_OPTS='-Xms【初始化内存大小】-Xmx【可以使用的最大内存】'需要把这个两个参数值调大。例如:JAVA_OPTS='-Xms256m -Xmx512m'表示初始化内存为256MB,可以使用的最大内存为512MB(普通PC机作为服务器下建议用此配置)。

    从实际应用的角度来说。-Xmx大了不是很好,垃圾回收需要更多的时间,但是thread问题就很大,配给JVM的内存数越大,tomcat所能开的thread数就越小,最后出现ava.lang.OutOfMemoryError: unable to create new native thread

    如果给jvm分配过多,剩余供OS使用,其中windowsdll占了一部分,但是你在JVM创建线程的时候,创建的是OS的线程,他要从剩余的空间中分配内存。如果没有可用内存,出现上述错误。

    如果是刀片4核,8G内存的服务器,如果布置两个tomcattomcat预置值建议可以设置为JAVA_OPTS='-Xms512m –Xmx1024m'

  • 监控tomcat的另一方法

    2011-03-26 11:34:34

    1 下载:
    http://www.lambdaprobe.org/downloads/1.7/probe.1.7b.zip
    2 解压缩后,把probe.war放到TOMCAT的webapps下,设置server.xml
    的context
    3 设置用户如下,在tomcat_user.xml中
       vi /usr/local/tomcat/conf//tomcat-users.xml

    <?xml version='1.0' encoding='utf-8'?>
    <tomcat-users>
            <role rolename="manager"/>
            <role rolename="standard"/>
            <role rolename="tomcat"/>
            <role rolename="admin"/>
            <role rolename="role1"/>
            <user username="tomcat" password="tomcat" roles="tomcat"/>
            <user username="both" password="tomcat" roles="tomcat,role1"/>
            <user username="probe" password="probe" roles="admin,manager"/>
            <user username="role1" password="tomcat" roles="role1"/>
    </tomcat-users>

    4 设置环境变量,获取服务器状态
    # vi /etc/profile
    JAVA_OPTS=-Dcom.sun.management.jmxremote
    export JAVA_OPTS
     windows 在startup.bat中加

    5 重启动服务器
    6 输入http://localhost/probe/,输入用户名和密码
    7 即可进入,这里比较精彩的是对内存的监视,动态显示了JVM的内存图表
  • SVN服务器同步备份

    2011-02-22 13:19:28

    SVN服务器同步备份步骤
    一、服务器准备
    主服务器:10.8.9.198
    备份服务器:10.8.9.51
    二、环境准备
    主服务器:windows xp+visualSVN
    备份服务器:windows xp+visualSVN
    建议visualSVN版本一致
    三、配置
    1、在备份服务器上创建与主服务器上同名,需同步的项目名如TEST(trunk、tags等目录不必创建),创建一用户xxx且xxx用户在主服务器中有读写权限;
    2、在备份服务器的项目管理目录中的hooks文件夹下,找到pre-revprop-change.tmpl文件,复制粘贴后改名为pre-revprop-change.bat,并清空文件内容
    3、在备份服务器上进入dos命令窗口,切换到svn安装目录的bin文件夹下运行svnsync init https://备份服务器IP:端口/svn/TEST https://主服务器IP:端口/svn/TEST(初始化同步)
    4、在主服务器的svn项目管理目录中的hooks文件夹下,找到post-commit.tmpl复制粘贴后改名为post-commit.bat
    5、在备份服务器的dos窗口,切换到svn安装目录的bin文件夹下运行svnsync sync https://备份服务器IP:端口/svn/TEST即可实现同步
    post-commit.bat内容如下
    echo off
    set SVN_HOME="D:\Program Files\VisualSVN Server\"
    %SVN_HOME%\bin\svnsync sync --non-interactive https://备份服务器IP:端口/svn/TEST --username xxx --password x  
  • linux下tomcat设置最大连接数,设置最大内存,使用jconsole监控

    2011-01-25 09:58:55

    关键字: linux下tomcat设置最大连接数,设置最大内存,使用jconsole监控
    1. 添加tomcat管理员帐户
    添加管理员账户tomcat-users.xml
    <?xml version='1.0' encoding='utf-8'?>
    <tomcat-users>
    <role rolename="tomcat"/>
    <role rolename="role1"/>
    <role rolename="manager"/>
    <role rolename="admin"/>
    <user username="tomcat" password="tomcat" roles="tomcat"/>
    <user username="both" password="tomcat" roles="tomcat,role1"/>
    <user username="role1" password="tomcat" roles="role1"/>
    <user username="admin" password="admin123" roles="admin,manager"/>
    </tomcat-users>

    2. TOMCAT内存
    基本原理:JAVA程序启动时都会JVM 都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能。比如说在应用程序用到最大内存的时候,JVM是要 先去做垃圾回收的动作,释放被占用的一些内存。 所以想调整Tomcat的启动时初始内存和最大内存就需要向JVM声明,一般的JAVA程序在运行都可以通过中-Xms -Xmx来调整应用程序的初始内存和最大内存:   如:java -Xms64m -Xmx128m application.jar.

    方法1:如果是使用的tomcat_home/bin/catalina.sh(linux)或catalina.bat(win)启动的:
    修改相应文件,加上下面这句:
    JAVA_OPTS='$JAVA_OPTS -server -Xmx800m -Xms512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless=true'--ms是最小内存,mx是最大内存。这里设置最小内存为512M,最大内存为 800M。$JAVA_OPTS是保留先前设置。 CATALINA_OPTS似乎可以与JAVA_OPTS不加区别的使用。[对于catalina.bat则是如此设置: set   JAVA_OPTS=-Xms1024m   -Xmx1024m]

    方法2:如果使用的winnt服务启动:
    在命令行键入regedit,找到 HKEY_LOCAL_MACHINE-->SOFTWARE-->Apache Software Foundation-->Procrun 2.0-->Tomcat5-->Parameters的Java,
    修改Options的值,新添加属性:
    -Xms64m
    -Xmx128m 或者直接修改JvmMx(最大内存)和JvmMs(最小内存)。

    有人建议Xms和Xmx的值取成一样比较好,说是可以加快内存回收速度。
    修改完之后,可以访问http://127.0.0.1:8080/manager/status查看内存大小。

    也可以编写下面测试tomcat内存大小的jsp页面:
    <%
    Runtime lRuntime = Runtime.getRuntime();
    out.println("*** BEGIN MEMORY STATISTICS ***<br/>");
    out.println("Free Memory: "+lRuntime.freeMemory()+"<br/>");
    out.println("Max   Memory: "+lRuntime.maxMemory()+"<br/>");
    out.println("Total Memory: "+lRuntime.totalMemory()+"<br/>");
    out.println("Available Processors : "+lRuntime.availableProcessors()+"<br/>");
    out.println("*** END MEMORY STATISTICS ***");
    %>

    3. 增加tomcat连接数
    在tomcat配置文件server.xml中的配置中,和连接数相关的参数有:
    minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10
    maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75
    acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100
    enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false
    connectionTimeout: 网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。 web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。
    如:
    <Connector   port="8080"  
          maxThreads="150"    
          minSpareThreads="25"    
          maxSpareThreads="75"  
          acceptCount="100"  
          />  
    maxThreads="150"     表示最多同时处理150个连接  
    minSpareThreads="25"     表示即使没有人使用也开这么多空线程等待  
    maxSpareThreads="75"     表示如果最多可以空75个线程,例如某时刻有80人访问,之后没有人访问了,则tomcat不会保留80个空线程,而是关闭5个空的。  
       
    acceptCount="100"   当同时连接的人数达到maxThreads时,还可以接收排队的连接,超过这个连接的则直接返回拒绝连接。

    4.使用Jconsole监控
    在需要监控的tomcat_home/bin/catalina.sh(linux)文件中添加下面语句:JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=8089
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false"
    设置一个新的端口号。然后在本机dos下输入Jconsole命令,弹出“JAVA 监视和管理控制台”,如果是远程监视,就输入<hostname>:<port>,这个port就上上面配置的8089,然后再输入远程主机的用户名跟口令,就可以监控啦。
    传说这里面还可以加一句话"-Djava.rmi.server.hostname=192.168.1.80" 
       服务器多网卡远程tomcat的jmx配置,多了个参数-Djava.rmi.server.hostname=ip_or_hostname。然后我就加上了服务器的IP。然后再连接就可以了。
  • loadrunner并发测试tomcat上应用

    2010-07-16 20:31:49

          在linux下,用loadrunner的winsocket协议在测试tomcat应用时,经常出现10053,10054的错误,无意间设置了下/etc/security/limit.inf文件的参数
    增加了 * - nofile 10240(此为增加文件打开数量);竟然没有出现错误了。


  • 修改svn日志信息

    2010-01-27 09:48:49

    服务器为windows方法:找到版本库中hooks目录下,将pre-revprop-change.tmpl复制为pre-revprop-change.bat
    然后修改pre-revprop-change.bat文件中最后内容为:代码:

    # Here is an example hook script, for a Unix /bin/sh interpreter.# For more examples and pre-written hooks, see those in
    # the Subversion repository at
    # [url]http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/[/url] and
    # [url]http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/[/url]
    rem Only allow log messages to be changed.
    if "%4" == "svn:log" exit 0
    echo Property '%4' cannot be changed >&2
    exit 1

    这样就可以修改日志了,上面最后三行的意思如下:
    如果修改的是svn:log(也就是日志)则返回0,通过,如果不是,输出要修改的不能被修改返回1

    Unix/Linux解决方案:
    只要将文件pre-revprop-change.tmpl改名为pre-revprop-change,并加上执行权限即可。具体步骤为右键点击属性,勾选执行权限。

  • 深刻理解Java编程的7个例子

    2009-11-10 15:36:45

     

     1. 阅读下列代码回答问题(第一个Java程序,理解PATH和CLASSPATH,学会使用javac和java命令)

    view plaincopy to clipboardprint?
    package cn.edu.uibe;  
    public class HelloWorld {  
        public static void main(String[] args) {  
            System.out.println("Hello World!");  
        }  

    package cn.edu.uibe;
    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
     

    问:

    (1)上面代码所在的源文件的文件名是_______________?
    (2)在DOS提示符下,当前目录为该源文件所在的目录,PATH环境变量已包含编译程序所在的路径,编译目标路径为“D:\classes”,编译命令行是_____________?
    (3)为了让Java解释器能够找到编译后的类文件,需要如何设置环境变量___________?
    (4)在正确设置了相关的环境变量之后,运行HelloWorld类的命令行是____________?


    答案:

    (1)HelloWorld.java,公共类必须定义在和类名同名的文件中,文件名区分大小写。

    (2)javac -d D:\classes HelloWorld.java ,-d给出输出目录,javac会在D:\classes创建包的目录层次结构cn\edu\uibe\HelloWorld.class

    (3)set CLASSPATH=.;D:\classses,CLASSSPATH给出Java寻找.class文件的多个路径,路径之间用分号分隔,“.”表示当前路径。

    (4)java cn.edu.uibe.HelloWorld,注意需要给出包名,类名后面不要加“.class”。

    2. 阅读下列代码回答问题(关于private的理解)

    view plaincopy to clipboardprint?
    public class Light {  
        private int brightness = 5;  
        public void brighten(Light another){  
            another.brightness++;  
        }  
        public static void main(String[] args) {  
            Light light1 = new Light();  
            Light light2 = new Light();  
            light1.brighten(light2);  
        }  

    public class Light {
     private int brightness = 5;
     public void brighten(Light another){
      another.brightness++;
     }
     public static void main(String[] args) {
      Light light1 = new Light();
      Light light2 = new Light();
      light1.brighten(light2);
     }
    }
     

    问:上面代码Java编译器是否会给出错误提示?为什么?

    答案:不会出现错误提示,private限制了私有变量只能被同一个类访问,但是没有限制同一个类的不同对象之间互相访问私有变量。实际上,private是在编译时进行检查,如果想限制同类对象之间互相访问,需要在动态运行时实现,开销较大,而且没有必要。

    3. 阅读下列代码回答问题(关于多态性的理解)

    view plaincopy to clipboardprint?
    class Base {  
        int i=1;  
        void f(){  
            System.out.println("Base.f()");  
        }  
        void g(){  
        f(); //会调用上面的f()方法吗?  
        }  
    }  
    public class Derived extends Base { //继承了Base类  
        int i=2; //Derived类的对象有1个i还是2个i呢? 答:2个  
        void f(){ //覆盖override了f()方法  
            System.out.println("Derived.f()");  
        }  
        public static void main(String[] args) {  
            Derived d = new Derived(); //创建子类对象  
            Base b = d; //没有创建对象,仅仅是父类引用指向了子类对象  
            d.f(); //将会输出Derived.f()  
            b.f(); //也会输出Derived.f(),方法具有多态性  
            System.out.println(d.i); //输出的是2,d.i访问子类中定义的变量i  
            System.out.println(b.i); //输出的是1,b.i访问的是父类中定义的变量i,成员变量是不会动态绑定而表现出多态性的。        
            d.g(); //输出Derived.f()  
            b.g(); //也输出Derived.f(),从父类中调用被覆盖的方法f(),也将调用到子类中更具体的方法。  
        }  

    class Base {
        int i=1;
        void f(){
            System.out.println("Base.f()");
        }
        void g(){
     f(); //会调用上面的f()方法吗?
        }
    }
    public class Derived extends Base { //继承了Base类
        int i=2; //Derived类的对象有1个i还是2个i呢? 答:2个
        void f(){ //覆盖override了f()方法
            System.out.println("Derived.f()");
        }
        public static void main(String[] args) {
            Derived d = new Derived(); //创建子类对象
            Base b = d; //没有创建对象,仅仅是父类引用指向了子类对象
            d.f(); //将会输出Derived.f()
            b.f(); //也会输出Derived.f(),方法具有多态性
            System.out.println(d.i); //输出的是2,d.i访问子类中定义的变量i
            System.out.println(b.i); //输出的是1,b.i访问的是父类中定义的变量i,成员变量是不会动态绑定而表现出多态性的。  
            d.g(); //输出Derived.f()
            b.g(); //也输出Derived.f(),从父类中调用被覆盖的方法f(),也将调用到子类中更具体的方法。
        }
    }
     

    问: 写出上面代码的输出?

    答案:参见代码注释,子类和父类中定义同名的变量时,仅仅是隐藏了,变量没有多态性;而对于覆盖的方法,Java表现出多态性,

    会调用更具体的子类里面的方法,无论从哪里调用,无论使用什么引用类型调用。

    4.阅读下列代码回答问题(关于匿名内部类的理解)

    view plaincopy to clipboardprint?
    interface A {  
        void f();  
    }  
    public class B {  
        public void f(A a) {  
        }  
        public static void main(String[] args) {  
            B b= new B();  
            b.f(new A() {  
                public void f() {  
                }  
            });  
        }  

    interface A {
        void f();
    }
    public class B {
        public void f(A a) {
        }
        public static void main(String[] args) {
            B b= new B();
            b.f(new A() {
                public void f() {
                }
            });
        }
    }
     

    问:请解释语句
    b.f(new A() {
        public void f() {
        }
    });
    的含义与作用。

    答案:

       这个语句在参数表中定义了一个匿名内部类,这个匿名内部类实现了接口A,实例化了一个匿名内部类的对象,并将这个对象传递给了接收接口A作为参数的方法f(A a)。需要注意的是接口A中的方法f()和类B中的方法f(A a)没有任何关系,是不同的方法。


    5. 阅读下列代码回答问题(关于static的理解)

    view plaincopy to clipboardprint?
    public class Static {  
        static int i = 0;  
        int j=0;  
        public static void main(String[] args) {  
            Static s1 = new Static();  
            Static s2 = new Static();  
            s1.i++;  
            s2.i++;  
            s1.j++;  
            s2.j++;  
            System.out.println(s1.i);  
            System.out.println(s1.j);  
            System.out.println(s2.i);  
            System.out.println(s2.j);  
    }  

    public class Static {
     static int i = 0;
     int j=0;
     public static void main(String[] args) {
      Static s1 = new Static();
      Static s2 = new Static();
      s1.i++;
      s2.i++;
      s1.j++;
      s2.j++;
      System.out.println(s1.i);
      System.out.println(s1.j);
      System.out.println(s2.i);
      System.out.println(s2.j);
    }
    }
     

    问:写出上面代码的输出。

    答案: 2 1 2 1,i是静态变量,类的所有实例共享同一个i,通常我们不通过引用变量访问静态变量,而是通过类名访问Static.i,注意Static是我们自己定义的类名,而小写的static是关键字,表示静态的,为类的所有实例共享的变量或方法。j是实例变量,每个对象具有不同的,属于其自身的一个变量j。

    6. 阅读下列代码回答问题(关于引用变量的理解)

    view plaincopy to clipboardprint?
    class Counter{  
        int i=0;  
    }  
    public class Reference {  
        public void plus(int i){  
            i++; //不会改变传递进来的参数的值,Java传递基本类型时进行了值的拷贝  
        }  
        public void plus(Counter c){  
            c.i++; //会改变,因为c是一个引用变量,相当于指针  
        }  
        public void create(Counter c){  
            c = new Counter();   
                      c.i++; //不会改变,因为c执行了另外一个新建的对象  
        }     
        public static void main(String[] args) {  
            int i = 0;  
            Reference r = new Reference();  
            Counter c1 = new Counter();  
            Counter c2 = new Counter();       
            r.plus(i);  
            r.plus(c1);  
            r.create(c2);         
            System.out.println(i);  
            System.out.println(c1.i);  
            System.out.println(c2.i);  
        }  

    class Counter{
     int i=0;
    }
    public class Reference {
     public void plus(int i){
      i++; //不会改变传递进来的参数的值,Java传递基本类型时进行了值的拷贝
     }
     public void plus(Counter c){
      c.i++; //会改变,因为c是一个引用变量,相当于指针
     }
     public void create(Counter c){
      c = new Counter();
                      c.i++; //不会改变,因为c执行了另外一个新建的对象
     } 
     public static void main(String[] args) {
      int i = 0;
      Reference r = new Reference();
      Counter c1 = new Counter();
      Counter c2 = new Counter();  
      r.plus(i);
      r.plus(c1);
      r.create(c2);  
      System.out.println(i);
      System.out.println(c1.i);
      System.out.println(c2.i);
     }
    }
     

    问:上面代码输出是?

    答案:参考代码注释,输出应该是:0 1 0

    7. 阅读下列代码回答问题(关于异常的理解)

    view plaincopy to clipboardprint?
    class MyException extends Exception{  
        public MyException(String message){  
            super(message);  
        }  
    }  
    public class ExceptionDemo{  
        public void f(int num) throws MyException {  
            if(num<0){  
                throw new MyException("参数不能为负数!");  
            }  
            System.out.println(num);  
            }  
        public void g(){  
            try{  
                f(1);  
                f(3);  
                f(0);  
                f(-1);  
                f(2);  
                f(-5);  
            }catch(MyException e){  
                System.err.println(e.getMessage());  
                return;//会立即返回吗?答:不会!  
            }finally{  
               System.out.println("无论什么时候!");     
            }  
        }  
        public static void main(String[] args) {  
            ExceptionDemo demo = new ExceptionDemo();  
            demo.g();  
        }  

    class MyException extends Exception{
     public MyException(String message){
      super(message);
     }
    }
    public class ExceptionDemo{
     public void f(int num) throws MyException {
      if(num<0){
       throw new MyException("参数不能为负数!");
      }
      System.out.println(num);
      }
     public void g(){
      try{
       f(1);
       f(3);
       f(0);
       f(-1);
       f(2);
       f(-5);
      }catch(MyException e){
       System.err.println(e.getMessage());
       return;//会立即返回吗?答:不会!
      }finally{
         System.out.println("无论什么时候!"); 
      }
     }
     public static void main(String[] args) {
      ExceptionDemo demo = new ExceptionDemo();
      demo.g();
     }
    }
     

    问:上面代码输出是?

    答案:输出是:1 3 0 参数不能为负数! 无论什么时候!

    try语句块里面的一行代码抛出了异常,后续代码就不再执行了,而是转到catch开始匹配异常类型。finally语句块里面的代码始终会被执行,即使在catch语句块里面有行return语句也不会立即返回,Java确保finally语句块执行完函数才会返回。

  • PHP学习(一)

    2009-04-02 21:54:18

Open Toolbar