一点题目(一)

1,switch语句能否作用在byte上,能否作用在long上,能否作用在String上?

  在jdk1.6之前,在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。

  今天自己动手之后发现

  switch("s")出现提示:Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted。

2,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;

  在动手之前自己想当然的以为是:s1 + 1会自己强制转换为short,但其实不然。

  Java数据类型的转换,分为自动转换和强制转换。

  自动转换时在程序执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;例如:

  short s1 = 1;

  int s2 = s1;

  强制类型转换则必须在代码中声明,转换顺序不受限制。 

  int s1 = 1;

  short s2 = (int)s1;

  题目中的“+=”是java语言规定的运算符,java编辑器会对它进行特殊处理,因此可以正常编译。

3,使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
4,Servlet

概念:

  全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态web内容。狭义的Servlet是指Java语言实现的一个接口,广义的servlet是指任务实现了这个Servlet的类。

  servlet运行于支持Java的应用服务器中。从实现上讲,servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

工作模式:

  客户端发送请求到服务器;

  服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器;

  服务器将响应返回客户端;

HttpServlet:

  javax.servlet.http.HttpServlet实现了专门用于响应HTTP请求的Servlet,提供了响应对应HTTP标准请求的doGet()、doPost()等方法。

生命周期:

  当servlet被部署在应用服务器中(应用服务器中用于管理Java组件的部分被抽象成为容器)以后,由容器控制servlet的生命周期。除非特殊指定,否则在容器启动的时候,servlet是不会被加载的,servlet只会在第一次请求的时候被加载和实例化。servlet一旦被加载,一般不会从容器中删除,直至应用服务器关闭或重新启动。但当容器做内存回收动作时,servlet有可能被删除。也正是因为这个原因,第一次访问servlet所用的时间要大大多于以后访问所用的时间。

  servlet在服务器的运行生命周期为,在第一次请求(或其实体被内存垃圾回收后再被访问)时被加载并执行一次初始化方法,跟着执行正式运行方法,之后会被常驻并每次被请求时直接执行正式运行方法,直到服务器关闭或被清理时执行一次销毁方法后实体销毁。

5,run方法和start方法

  start方法

  用start方法来启动线程,是真正实现了多线程,通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程。
  run方法

  run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。

6,HttpSession session = request.getSession(false) 与HttpSession session = request.getSession(true)的区别?

HttpSession session = request.getSession(boolean create) ;
返回当前请求的会话,如果当前请求不属于任何会话,而且create参数为true,则创建一个会话,否则返回null。此后所有来自同一个请求都属于这个会话,通过它的getSession返回的是当前会话。

7,String和StringBuffer的区别

(1)String是不可变的对象,StringBuffer是可以再编辑的;
(2)String是常量,StringBuffer是变量;
(3)String、StringBuffer、StringBuilder
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都是String类的对象。字符串是常量;它们的值在创建之后不能改变。所以可以共享它们。StringBuffer是字符串缓存区,它的内容可以被修改,长度也可以改变,StringBuffer类是线程安全的,也就是说多个线程可以安全的访问StringBuffer对象。StringBuilder与StringBuffer类似,都是字符串缓冲区,但StringBuilder不是线程安全的,如果你只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些。值得注意的是StringBuilder是在JDK1.5版本中增加的。以前版本的JDK不能使用该类。

8,JVM的垃圾回收方式:

jvm性能调优/垃圾回收器


9,在Java中,声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能给定数组长度。

例如:String a[] = new String[50]; String b[];char c[]; 是对的,String d[50]; char a[50];是错的

10,Java关于继承的描述

(1)一个子类只能继承一个父类
(2)继承具有传递性
(3)父类一般具有通用性,子类更具体
(4)子类可以继承父类的构造方法(错误)
(5)在java中,子类构造器会默认调用super()(无论构造器中是否写有super()),用于初始化父类成员,同时当父类中存在有参构造器时,必须提供无参构造器,子类构造器中并不会自动继承有参构造器,仍然默认调用super(),使用无参构造器。因此,一个类想要被继承必须提供无参构造器。
(6)方法没有继承一说,只有重载和重写

11,Servlet的生命周期一般可以用三个方法来表示:

init():仅执行一次,负责在装载Servlet时初始化Servlet对象
service():核心方法,一般HttpServlet中会有get,post两种处理方式。在调用doGet和doPost方法时会构造servletRequest和servletResponse请求和响应对象作为参数。
destory():在停止并且卸载Servlet时执行,负责释放资源
初始化阶段:Servlet启动,会读取配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,将ServletConfig作为参数来调用init()方法。所以选ACD。B是在调用service方法时才构造的

12,String str = new String(“abc”),“abc”在内存中是怎么分配的?

堆和字符串常量区
参考:
什么是字符串常量池
JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池

工作原理
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。

实现前提
字符串常量池实现的前提条件就是Java中String对象是不可变的,这样可以安全保证多个变量共享同一个对象。如果Java中的String对象可变的话,一个引用操作改变了对象的值,那么其他的变量也会受到影响,显然这样是不合理的。

更详细的关于字符串常量池 http://droidyue.com/blog/2014/12/21/string-literal-pool-in-java/

关于堆和栈
Java中所有由类实例化的对象和数组都存放在堆内存中,无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。而栈内存用来存储局部变量和方法调用。
更详细的关于堆和栈的区别 http://droidyue.com/blog/2014/12/07/differences-between-stack-and-heap-in-java/

关于寄存器
Java中运行时数据区有一个程序寄存器(又称程序计数器),该寄存器为线程私有。Java中的程序计数器用来记录当前线程中正在执行的指令。如果当前正在执行的方法是本地方法,那么此刻程序计数器的值为undefined
关于JVM运行时数据区的 http://droidyue.com/blog/2014/12/21/java-runtime-data-areas/

关于本题目中,"abc"为字面量对象,其存储在堆内存中。而字符串常量池则存储的是字符串对象的一个引用。

13,request的forward和response的redirect

1.redirect地址栏变化,forward发生在服务器端内部从而导致浏览器不知道响应资源来自哪里
2.redirect可以重定向到同一个站点上的其他应用程序中的资源,forward 只能将请求 转发给同一个WEB应用中的组件
3.redirect默认是302码,包含两次请求和两次响应
4.redirect效率较低

14,代码片段

byte b1=1,b2=2,b3,b6;
final byte b4=4,b5=6;
b6=b4+b5;
b3=(b1+b2);
System.out.println(b3+b6);
解析:
语句:b3=b1+b2编译出错,被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10了
而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换。
Java中的byte,short,char进行计算时都会提升为int类型。

15,volatile关键字

(1)用volatile修饰的变量,每次更新对其他线程都是立即可见的。
(2)对volatile变量的操作是原子性的。(错误)
(3)对volatile变量的操作不会造成阻塞。
(4)不依赖其他锁机制,多线程环境下的计数器可用volatile实现。(错误)
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值——每次都会从内存中读取。
而对该变量的修改,volatile并不提供原子性的保证。
由于及时更新,很可能导致另一线程访问最新变量值,无法跳出循环的情况
多线程下计数器必须使用锁保护。

posted @ 2016-01-31 13:17  lemon-now  阅读(309)  评论(0编辑  收藏  举报