Java概念性问题6

有以下代码片段:请问输出的结果是:D
String str1="hello";
String str2="he"+ new String("llo");
System.out.println(str1==str2);

A true
B 都不对
C null
D false
String str1=“hello”; 这样创建字符串是存在于常量池中
String str2=new String(“hello”); str2存在于堆中,
==是验证两个对象是否是一个(内存地址是否相同)
用+拼接字符串时会创建一个新对象再返回。


1)String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法。在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。
2)String类底层是char数组来保存字符串的。对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

字符串常量池
在class文件中有一部分来存储编译期间生成的字面常量以及符号引用,这部分叫做class文件常量池,在运行期间对应着方法区的运行时常量池。
JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池
工作原理
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用。
实现前提
字符串常量池实现的前提条件就是Java中String对象是不可变的,这样可以安全保证多个变量共享同一个对象。如果Java中的String对象可变的话,一个引用操作改变了对象的值,那么其他的变量也会受到影响,显然这样是不合理的。

String str1 = “hello”;
这里的str1指的是方法区中的字符串常量池中的“hello”,编译时期就知道的;
String str2 = “he” + new String(“llo”);
这里的str2必须在运行时才知道str2是什么,所以它是指向的是堆里定义的字符串“hello”,所以这两个引用是不一样的。
如果用str1.equal(str2),那么返回的是true;因为String类重写了equals()方法。
编译器没那么智能,它不知道"he" + new String(“llo”)的内容是什么,所以才不敢贸然把"hello"这个对象的引用赋给str2.
如果语句改为:“he”+"llo"这样就是true了。
new String(“zz”)实际上创建了2个String对象,就是使用“zz”通过双引号创建的(在字符串常量池),另一个是通过new创建的(在堆里)。只不过他们的创建的时期不同,一个是编译期,一个是运行期。
String s = “a”+“b”+“c”;
语句中,“a”,“b”, "c"都是常量,编译时就直接存储他们的字面值,而不是他们的引用,在编译时就直接将它们连接的结果提取出来变成"abc"了。

下列属于容器的组件有(B)

A JButton
B JPanel
C Thread
D JTextArea
容器java.awt.Container是Component的子类,一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。
有三种类型的容器:Window、Panel、ScrollPane,常用的有Panel, Frame, Apple

JDK中提供的java、javac、jar等开发工具也是用Java编写的。(正确)
多态性

多态性:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
1)多态存在的三个必要条件
①要有继承 ②要有重写 ③父类引用指向子类对象(向上转型)
2)实现多态性的三种形式
①方法的重载 ②通过继承机制而产生方法覆盖 ③通过接口实现方法覆盖
3)多态的分类
多态分为编译时多态和运行时多态。其中编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编译之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们平常所说的多态性。

JSP分页代码中,哪个步骤次序是正确的?A

A 先取总记录数,得到总页数,再取所有的记录,最后显示本页的数据。
B 先取所有的记录,得到总页数,再取总记录数,最后显示本页的数据。
C 先取总页数,得到总记录数,再取所有的记录,最后显示本页的数据。
D 先取本页的数据,得到总页数,再取总记录数,最后显示所有的记录。

//1.查询得到rowCount
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
Connection ct=DriverManager.getConnection("jdbc:microsoft:sqlserver://127.0.0.1:1433;dataBaseName=System","sa","");
Statement sm=ct.createStatement();
ResultSet rs=sm.exeuteQuery("select count(*) form users "); if(rs.next()){
rowCount=rs.getInt(1);
} //2。计算pageCount if(rowCount%pageSize==0){
pageCount=rowCount/pageSize;
}else{
pageCount=rowCount/pageSize+1;
} //3.4查询出需要显示的记录
rs=sm.exeuteQuery("select top "+pageSize +" * from users where userId not in(select top " +pageSize*(pageNow-1)+" userId from users) "); %> //显示
下面哪个标识符是合法的?D

A “9HelloWorld”
B “_Hello World”
C "HelloWorld"
D “Hello$World”
标识符:
用来表示变量名,方法名,类名,数组名和文件名的有效字符序列。
也就是说,任何一个变量,常量,方法,对象和类都需要有名字,这些名字就是标识符。
规定如下:
(1)标识符可以由数字、字母、下划线或美元符号等组合而成。
(2)必须以字母、下划线或者美元符号开头,不能以数字开头路。
A有字母,错。
B有空格,错。
C有非法字符
,错。

JAVA反射机制主要提供了以下哪些功能?ABCD

A 在运行时判断一个对象所属的类
B 在运行时构造一个类的对象
C 在运行时判断一个类所具有的成员变量和方法
D 在运行时调用一个对象的方法
  普通的java对象是通过new关键字把对应类的字节码文件加载到内存,然后创建该对象的。 反射是通过一个名为Class的特殊类,用Clas敏感词orName(“className”);得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)。 也就是说反射机制让我们可以先拿到java类对应的字节码对象,然后动态的进行任何可能的操作。

JAVA反射机制概念:
  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:
  在运行时判断任意一个对象所属的类;
  在运行时构造任意一个类的对象;
  在运行时判断任意一个类所具有的成员变量和方法;
  在运行时调用任意一个对象的方法;
  生成动态代理。

得到该对象所属的类: Class ownerClass = owner.getClass()
在运行时构造一个类的对象:
Class newoneClass = Class.forName(className):第一步,得到要构造的实例的Class。
Constructor cons = newoneClass.getConstructor(argsClass):得到构造子。cons.newInstance(args):新建实例。
在运行时判断一个类所具有的成员变量和方法:
Class ownerClass = owner.getClass():得到该对象的Class。
Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。 Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
在运行时调用一个对象的方法:
Method method = ownerClass.getMethod(methodName, argsClass):通过Method名和参数的Class数组得到要执行的Method。
method.invoke(owner, args):执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既是该方法的返回值。

下列说法正确的是B

A 在类方法中可用this来调用本类的类方法
B 在类方法中调用本类的类方法可直接调用
C 在类方法中只能调用本类的类方法
D 在类方法中绝对不能调用实例方法

在类方法中调用本类的类方法可直接调用。 实例方法也叫做对象方法。
类方法是属于整个类的,而实例方法是属于类的某个对象的。
由于类方法是属于整个类的,并不属于类的哪个对象,所以类方法的方法体中不能有与类的对象有关的内容。即类方法体有如下限制:
(1) 类方法中不能引用对象变量;
(2) 类方法中不能调用类的对象方法;
(3) 在类方法中不能使用super、this关键字。
(4)类方法不能被覆盖。
如果违反这些限制,就会导致程序编译错误。
与类方法相比,对象方法几乎没有什么限制:
(1) 对象方法中可以引用对象变量,也可以引用类变量;
(2) 对象方法中可以调用类方法;
(3) 对象方法中可以使用super、this关键字。

D 类方法中可以创建对象,进而调用实例方法

Thread. sleep()是否会抛出checked exception?会

Thread.sleep() 和 Object.wait(),都可以抛出 InterruptedException。这个异常是不能忽略的,因为它是一个检查异常(checked exception)

checkedexception:指的是编译时异常,该类异常需要本函数必须处理的,用try和catch处理,或者用throws抛出异常,然后交给调用者去处理异常。
runtime exception:指的是运行时异常,该类异常不必须本函数必须处理,当然也可以处理。
Thread.sleep()抛出的InterruptException属于checked exception;IllegalArgumentException属于Runtime exception;

关于下列程序段的输出结果,说法正确的是:(D )
public class MyClass{
 static int i; public static void main(String   argv[]){
  System.out.println(i); } }

A 有错误,变量i没有初始化。
B null
C 1
D 0

ServletConfig接口默认是哪里实现的?B

A Servlet
B GenericServlet
C HttpServlet
D 用户自定义servlet
  GenericServlet类的实现接口中包括了ServletConfig接口,但是它自身的init(ServletConfig config)方法又需要外界给它传递一个实现ServletConfig的对象,就是说GenericServlet和ServletConfig的依赖关系既是继承关系,也是一种关联关系

public abstract class GenericServlet
extends java.lang.Object
implements Servlet, ServletConfig, java.io.Serializable
从Servlet 的API文档上面可以看到上面一段,
抽象类GenericServlet实现了Servlet, ServletConfig等接口。

public abstract class HttpServlet extends GenericServlet
implements java.io.Serializable
抽象类HttpServlet 继承自GenericServlet

关于sleep()和wait(),以下描述错误的一项是(D)

A sleep是线程类(Thread)的方法,wait是Object类的方法;
B sleep不释放对象锁,wait放弃对象锁
C sleep暂停线程、但监控状态仍然保持,结束后会自动恢复
D wait后进入等待锁定池,只有针对此对象发出notify方法后获得对象锁进入运行状态

Java中的多线程是一种抢占式的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。
共同点:

  1. 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
  2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态,从而使线程立刻抛出InterruptedException。 如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch(){} 中直接return即可安全地结束线程。
    需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入wait()/sleep()/join()后,就会立刻抛出InterruptedException 。
    不同点:
    1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。 sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
    2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
    3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
    4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
    5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。//不直接进入运行状态

一. 线程状态类型

  1. 新建状态(New):新创建了一个线程对象
  2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权
  3. 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码
  4. 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
    (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中
    (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中
    (三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态
  5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
    线程状态图
    这里写图片描述
AWT&Swing

AWT和Swing都是java中的包。
AWT(Abstract Window Toolkit):抽象窗口工具包,早期编写图形界面应用程序的包。
Swing :为解决 AWT 存在的问题而新开发的图形界面包。Swing是对AWT的改良和扩展。
AWT和Swing的实现原理不同:
AWT的图形函数与操作系统提供的图形函数有着一一对应的关系。也就是说,当我们利用 AWT构件图形用户界面的时候,实际上是在利用操作系统的图形库。不同的操作系统其图形库的功能可能不一样,在一个平台上存在的功能在另外一个平台上则可能不存在。为了实现Java语言所宣称的"一次编译,到处运行"的概念,AWT不得不通过牺牲功能来实现平台无关性。因此,AWT 的图形功能是各操作系统图形功能的“交集”。因为AWT是依靠本地方法来实现功能的,所以AWT控件称为“重量级控件”。

而Swing ,不仅提供了AWT 的所有功能,还用纯粹的Java代码对AWT的功能进行了大幅度的扩充。例如:并不是所有的操作系统都提供了对树形控件的支持, Swing则利用了AWT中所提供的基本作图方法模拟了一个树形控件。由于 Swing是用纯粹的Java代码来实现的,因此Swing控件在各平台通用。 因为Swing不使用本地方法,故Swing控件称为“轻量级控件”。

AWT和Swing之间的区别:
1)AWT 是基于本地方法的C/C++程序,其运行速度比较快;Swing是基于AWT的Java程序,其运行速度比较慢。
2)AWT的控件在不同的平台可能表现不同,而Swing在所有平台表现一致。
在实际应用中,应该使用AWT还是Swing取决于应用程序所部署的平台类型。例如:
1)对于一个嵌入式应用,目标平台的硬件资源往往非常有限,而应用程序的运行速度又是项目中至关重要的因素。在这种矛盾的情况下,简单而高效的AWT当然成了嵌入式Java的第一选择。
2)在普通的基于PC或者是工作站的标准Java应用中,硬件资源对应用程序所造成的限制往往不是项目中的关键因素。所以在标准版的Java中则提倡使用Swing, 也就是通过牺牲速度来实现应用程序的功能。

覆盖与隐藏

重载:方法名相同,但参数不同的多个同名函数   
注意:
1.参数不同的意思是参数类型、参数个数、参数顺序至少有一个不同      
2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg:void a ()和int a() ,如果调用a(),出现歧义)      
3.main方法也是可以被重载的
覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同    两同两小一大   
注意:子类实例方法不能覆盖父类的静态方法;子类的静态方法也不能覆盖父类的实例方法(编译时报错),总结为方法不能交叉覆盖
隐藏:父类和子类拥有相同名字的属性或者方法时,父类的同名的属性或者方法形式上不见了,实际是还是存在的   
注意:当发生隐藏的时候,声明类型是什么类,就调用对应类的属性或者方法,而不会发生动态绑定     
方法隐藏只有一种形式,就是父类和子类存在相同的静态方法     
属性只能被隐藏,不能被覆盖     
子类实例变量/静态变量可以隐藏父类的实例/静态变量,总结为变量可以交叉隐藏
隐藏和覆盖的区别:   
被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性   
被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法   
因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏
特殊情况:   
1.final修饰的属性可以被隐藏,但是不能被赋值,即不能用=来赋值,网上说final属性不能被修改,这个说法不准确,因为对于引用类型的变量用final修饰后,它只是不能被指向其他对象,但是可以改它自身的值,可以用ArrayList测试,final属性可以在运行的时候进行初始化,但是不能不出现初始化语句   
2.final修饰的方法不能被覆盖,可以被重载   
3.final修饰的类不能被继承   
4.private 方法隐式添加了final

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值