java概念 复习总结及题目.docx
《java概念 复习总结及题目.docx》由会员分享,可在线阅读,更多相关《java概念 复习总结及题目.docx(21页珍藏版)》请在冰点文库上搜索。
java概念复习总结及题目
JAVA概念
1.去掉了头文件、指针变量、结构、运算符重载、多重继承等
2.Java不支持预处理功能。
C/C++在编译过程中都有一个预编泽阶段,即众所周知的预处理器。
预处理器为开发人员提供了方便,但增加了编译的复杂性。
Java虚拟机没有预处理器,但它提供的引入语句(import)与C++预处理器的功能类似。
3.java方法不支持参数缺省值,因为这会与重载冲突
4.Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使用,还有const
5.Java不支持C++中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
6.装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。
比如:
把int转化成Integer,反之就是拆箱。
Integera=newInteger(3);
Integerb=3;//将3自动装箱成Integer类型
intc=3;
System.out.println(a==b);//false两个引用没有引用同一对象
System.out.println(a==c);//truea自动拆箱成int类型再和c比较
7.一个".java"源文件中是否可以包括多个类(不是内部类)但只能有一个public的类,并且public的类名必须与文件名相一致。
8.不通过构造函数也能创建对象
9.不可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用,
静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有被初始化。
10.内部类可以引用它的包含类(外部类)的成员,包括私有成员//私有成员不能被其他类访问XXX?
11.override覆盖(重写):
名称、返回类型和参数列表与父类中的相同(参数列表又叫参数签名,包括参数的类型、个数和顺序)
Ø被覆盖的方法在子类中只能通过super调用。
覆盖不会删除父类中的方法,而是对子类的实例隐藏
Ø如果覆盖的是成员变量,this.age与super.age是一个
覆盖的原则:
覆盖方法不能比原方法访问性差(即访问权限不允许缩小)。
覆盖方法不能比原方法抛出更多或更高级(EXception>ioException)的异常。
被覆盖的方法不能是final类型,因为final修饰的方法是无法覆盖的。
被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
*
被覆盖的方法不能为static。
如果父类中的方法为静态的,而子类中的方法不是静态的,那么会发生编译错误;反之亦然。
即使都是静态的,仍然不会发生覆盖,因为静态方法是在编译的时候把静态方法和类的引用类型进行匹配。
声明为static的方法不能被重写,但是能够被再次声明。
对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
*
覆盖和重载的不同:
覆盖要求参数列表必须一致,而重载要求参数列表必须不一致。
*
覆盖要求返回类型必须一致,重载对此没有要求。
覆盖对方法的访问权限和抛出的异常有特殊的要求,而重载在这方面没有任何限制。
Ø不能仅通过返回类型重载:
因为有时候调用一个方法时可以不定义返回结果变量,例如,我们调用 map.remove(key) 方法时,虽然remove方法有返回值,但是我们通常都不会定义接收返回结果的变量,这时候假设该类中有两个名称和参数列表完全相同的方法,仅仅是返回类型不同*
Ø不能通过访问权限、返回类型、抛出的异常、只改为兼容的形参类型,int->long进行重载,总之从编译器角度思考
Ø构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。
12.Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
13.接口中所有的方法隐含的都是抽象的。
而抽象类则可以同时包含抽象和非抽象的方法。
类如果要实现一个接口,它必须要实现接口声明的所有方法。
但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
抽象类可以在不提供接口方法实现的情况下实现接口。
Java接口中声明的变量默认都是final的。
抽象类可以包含非final的变量。
Java接口中的成员函数默认是public的。
抽象类的成员函数可以是private,protected或者是public。
接口是绝对抽象的,不可以被实例化。
抽象类也不可以被实例化,但如果它包含main方法的话是可以被调用的
14.关于接口:
接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的
接口中的方法都是抽象(abstract)方法,故接口可以用abstract修饰
接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有静态变量;
接口的中的变量是所有实现类共有的,既然共有,肯定是不变的东西,也就是final常量了。
综上,属性默认是publicstaticfinal ,方法默认是publicabstract,按定义final和abstract不能同时出现
15.关于继承构造函数的调用
子类的构造过程中必须调用其父类的构造函数,是因为有继承关系存在时,子类要把父类的内容继承下来。
如果父类有多个构造函数:
子类的构造过程中必须调用其父类的构造函数,如果在子类构造方法中我们并没有显示的调用基类的构造方法,如:
super();这样就会调用父类没有参数的构造方法。
如果子类的构造方法中既没有显示的调用基类构造方法,而基类中又没有无参的构造方法,则编译出错,所以,通常我们需要显示的:
super(参数列表),来调用父类有参数的构造函数,此时无参的构造函数就不会被调用。
总之:
子类没有显示调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错。
例
16.如果x.equals(y)==true,它们的哈希码应当相同,如果两个对象的hashCode相同,它们并不一定相同
使用==操作符检查“参数是否为这个对象的引用”
使用instanceof操作符检查“参数是否为正确的类型”
17.接口可以继承接口。
抽象类可以实现(implements)接口,抽象类可继承具体类,但前提是具体类必须有明确的构造函数。
18.创建对象时构造器的调用顺序是:
先初始化静态成员(先父后子),然后调用父类构造器,再初始化非静态成员,最后调用自身构造器,下次再创建对象时不再初始化静态域。
19.不可以在static环境中访问非static变量,理由如上
classA{
static{
a=1;
}
Inta;
20.round 方法参数加 1/2 后求其floor,所以Math.round(11.5)==12 Math.round(-11.5)==-11
21.关于String:
赋值:
(1)通过new:
Stringstr=newString("Hello");系统会先创建一个匿名对象"Hello"存入堆内存(暂且叫它A),然后new关键字会在堆内存中又开辟一块新的空间,然后把"Hello"存进去,并且把地址返回给栈内存中的str,此时A对象成为了一个垃圾对象,因为它没有被任何栈中的变量指向,会被GC自动回收。
同时会在字符串常量区(静态)创建一个字符串”Hello”,这个”Hello”伴随程序消亡
(2)直接赋值:
Stringstr="Hello"; 首先会去缓冲池中找有没有一个"Hello"对象,如果没有,则新建一个,并且入池,所以此种赋值有一个好处,下次如果还有String对象也用直接赋值方式定义为“Hello”或是”He”+”llo”,则不需要开辟新的堆空间,而仍然指向这个池中的"Hello"
//直接赋值的话,是通过编译器在起作用,当你对"abc"没有通过new创建时,他会自动默认给你调用构造函数newString(charvalue[]).不显式调用String的构造函数(通过new叫显式调用)
(3)手动入池(intern方法):
Stringstr1=newString("Hello").intern();
Stringstr2="Hello";
System.out.println(str1==str2);//true
初始化及运算:
Stringstr1="hello";Stringstr2="he"+newString("llo");System.err.println(str1==str2);//false
而Stringstr1="hello";Stringstr2=str1;System.err.println(str1==str2);//true
Stringstr1="hello";Stringstr2=str1+””;System.err.println(str1==str2);false//==判断的是地址而非值
str1是字符串常量所以在编译期就被确定了!
而str2中有个str1是引用不是字符串常量所以不会在编译期确定。
而String是final的!
所以在str1+””的时候实际上是新创建了一个对象,然后在把新创建对象的引用传给str2
故#Strings="Hello";s=s+"world!
”;原始的String对象没变,s指向了个新对象,但注意,字符串作为常量放在静态区里,即使栈中无指向它的变量,它还存在(静态区的内容在总个程序的生命周期内都存在,由编译器在编译的时候分配)故如果再s+=”“静态区又会占内存,这种操作频繁时内存开销很大,应用Stringbuffer类
#String不是最基本的数据类型,Java中的基本数据类型只有,8个,除了基本类型和枚举类型,剩下的都是引用类型
#数组没有length()方法,有length的属性。
String有length()方法,没有length属性.
#String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。
而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改。
StringBuilder 和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,效率高,而在字符常量池(静态存储区)中若有字符串连接结果,如有”abc”,则”a”+”bc”优于后两者的append方法//静态的叫法更好些,只有一个且公有
#Strings3="a"+"b";System.out.println(s3=="ab");//true
Javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。
#程序中的字面量(literal)如直接书写的100、“hello”和常量都是放在静态存储区中
22.关于异常
1)java.lang.Error:
Throwable的子类,用于标记严重错误。
合理的应用程序不应该去try/catch这种错误。
绝大多数的错误都是非正常的,就根本不该出现的。
java.lang.Exception:
Throwable的子类,用于指示一种合理的程序想去catch的条件。
即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。
#error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
2)Error和RuntimeException及其子类都是未检查的异常(uncheckedexceptions),而所有其他的Exception类都是检查了的异常(checkedexceptions)
#checkedexceptions:
通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。
比如FileNotFoundException,ParseException等。
检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
uncheckedexceptions:
通常是如果一切正常的话本不该发生的异常,但是的确发生了。
发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。
比如ArrayIndexOutOfBoundException,ClassCastException等。
程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是这类错误本身就是bug,应该被修复
#RuntimeException:
RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。
处理RuntimeException的原则是:
如果出现RuntimeException,那么一定是程序员的错误。
例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
其他(IOException等等)checked异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
#Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。
#运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。
受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发,Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常
23.关于线程:
创建:
3种方式
1)Runnable接口
threadOb是一个实现Runnable接口的类的实例,再以这个对象实例创建Thread对象来start线程
newThread(threadob,threadName).start()
或是直接将此句放到接口实现类的某个方法里如,start(自定义的非thread类里的)或构造器里
2)继承Thread类
#start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程,进而调用run()方法来执行任务,而单独的调用run()就跟调用普通方法是一样的,已经失去线程的特性了。
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。
结果就是两个进程都陷入了无限的等待中。
同步:
synchronized方法synchronized代码块
synchronized(object){//取得对象的互斥锁
object.s+="plus";
System.out.println(object.s);
}//结束即释放掉了
同步代码块使用的锁可以是任意对象。
同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象。
在一个类中只有一个同步的话,可以使用同步函数。
如果有多同步,必须使用同步代码块,来确定不同(对象)的锁。
线程通信:
wait(),notify()和notifyAll()方法配合同步的互斥锁
生命周期:
优先级:
一个整数,其取值范围是1(Thread.MIN_PRIORITY)-10(Thread.MAX_PRIORITY)默认5
24.关于静态:
在静态成员函数中没有this指针,所以不能使用非静态成员
floata;
publicstaticvoidmain(String[]args){
System.out.println(a);//编译报错加static后输出0.0
}
以InputStream(输入)/OutputStream(输出)为后缀的是字节流;以Reader(输入)/Writer(输出)为后缀的是字符流
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。
可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。
序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implementsSerializable只是为了标注该对象是可被序列化的.
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。
因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
克隆:
1.实现Cloneable接口并重写Object类中的clone()方法;
2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
JDK,JRE和JVM
Java开发工具包是Java环境的核心组件,并提供编译、调试和运行一个Java程序所需的所有工具
JVM负责将字节码转换为特定机器代码,是平台特定的,并提供核心的Java方法,例如内存管理、垃圾回收和安全机制等。
JRE是JVM的实施实现,它提供了运行Java程序的平台。
JRE包含了JVM、Java二进制文件和其它成功执行程序的类文件。
JRE不包含任何像Java编译器、调试器之类的开发工具。
执行Java程序,只需安装JRE即可,没有安装JDK的必要。
JDK是用于开发的而JRE是用于运行Java程序的。
JDK和JRE都包含了JVM,从而使得我们可以运行Java程序。
1.不通过构造函数也能创建对象?
是
(1)用new语句创建对象,这是最常见的创建对象的方法。
(2)运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
(3)调用对象的clone()方法。
(4)运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。
(1)和
(2)都会明确的显式的调用构造函数;(3)是在内存上对已有对象的影印,所以不会调用构造函数;(4)是从文件中还原类的对象,也不会调用构造函数。
2.constructor必须与class同名,但方法不能与class同名?
X普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值。
8.Java接口的修饰符可以为?
A.private
B.protected
C.final
D.abstract
答案:
CD
9.下面是People和Child类的定义和构造方法,每个构造方法都输出编号。
在执行newChild("mike")的时候都有哪些构造方法被顺序调用?
请选择输出结果
classPeople{
Stringname;
publicPeople(){
System.out.print
(1);
}
publicPeople(Stringname){
System.out.print
(2);
this.name=name;
}
}
classChildextendsPeople{
Peoplefather;
publicChild(Stringname){
System.out.print(3);
this.name=name;
father=newPeople(name+":
F");
}
publicChild(){
System.out.print(4);
}
}
A.312
B.32
C.432
D.132
答案:
D
nullinstanceofobject==false的几种解释
Primitivetypes(int, bool,etc.)aren'tsubtypesof Object
Strings=""; referencesaStringobjectwhoseinnercontent(achararray)isempty.
Strings=null isn'treferencinganything.
Asthe JLS says, null isofthenulltypeandthatisnotareferencetype.
Null和Object都是javascript中的数据类型。
Null数据类型只有一个值:
null
对于Null类型的值(只有null),规范就是定义返回"object"这个字符串。
但是本质上Null和Object不是一个数据类型,null值并不是以Object为原型创建出来的。
所以null instanceof Object是false。
故””+nullinstanceofobject==true
13.指出下面程序的运行结果:
classA{
static{
System.out.print("1");
}
publicA(){
System.out.print("2");
}
}
classBextendsA{
static{
System.out.print("a");
}
publicB(){
System.out.print("b");
}
}
publicclassHello{
publicstaticvoidmain(String[]args){
Aab=newB();
ab=newB();
}
}
答:
执行结果:
1a2b2b
16.判断下列语句是否正确,如果有错误,请指出错误所在?
interfaceA{
intadd(finalAa);
}
classBimplementsA{
longadd(finalAa){
returnthis.hashCode()+a.hashCode();
}
}
答:
返回值不是long类型