1、Java有几种修饰符,分别用来修饰什么?
访问权限 类 包 子类 其他包
public ∨ ∨ ∨ ∨
protect ∨ ∨ ∨ ×
default ∨ ∨ × ×
private ∨ × × ×
2、super什么时候使用?
子类的构造函数中不是必须使用super的,在构造函数中,如果第一行没有写super(),编译器会自动插入,如果父类没有不带参数的构造函数,或者这个函数被私有化了,此时必须加入对父类的实例化构造。而this没有这个要求,因为它本身就进行实例化的构造。如果父类的构造函数是无参的,那子类构造函数会在第一行默认调用super()。
3、public static void 写成 static public void会怎样?
本质上没有区别,编译器可以正常解析。
4、说明一下public static void main(String args[])这段声明里每个关键字的作用
public main方法是Java程序运行时调用的第一个方法,它必须对Java环境可见,所以可见性设置为public。
static:Java平台调用这个方法时不会创建这个类的一个实例,因此这个方法必须声明为static。
void:main方法没有返回值。
String是命令行传进参数的类型,args是指命令行传进的字符串数组。
5、sizeof 是Java 的关键字吗?
不是,Java是一种纯面向对象的编程语言,它将内存管理都交给JVM。同时Java是一种跨平台的语言,可移植性好,它的数据类型在不同机器中的大小都相同。
6、static class与non static class的区别?
静态内部类:
1)使用static修饰的内部类,属于外部类,而不是外部类的对象,又叫类内部类。
2)静态内部类可以包含静态成员和非静态成员。
3)静态内部类不能访问外部类的实例成员,只能访问外部类的静态成员。
4)接口内部类只能是静态内部类。
非静态内部类:
1)可以访问外部类的private成员,但非静态内部类的成员不能被外部类直接使用,如需访问则必须要创建非静态内部类的对象进行访问。
2)非静态内部类访问变量x,首先判断是否存在局部变量x,如果存在则使用该变量;如果没有,判断是否存在非静态内部类成员变量x,如果存在则使用该变量;如果没有,判断是否存在外部类成员变量x,如果存在则使用该变量;如果没有,系统出现编译错误。
3)如果外部类成员变量、内部类成员变量和局部变量重名,则通过外部类类名.this.变量名、this.变量名和变量名区分。
7、static关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法?
static表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。java中也不可以覆盖private的方法,因为private修饰的变量和方法只能在当前类中使用,如果是其他的类继承当前类是不能访问到private变量或方法的,也不能覆盖。
8、静态类型有什么特点?
静态变量是和类绑定到一起的,而不是类的实例对象。每一个实例对象都共享同样一份静态变量。一个类的静态变量只有一份,不管它有多少个对象。类变量或者静态变量是通过static这个关键字来声明的,类变量通常被用作常量,静态变量通常通过类名字来进行访问。当程序运行的时候这个变量就会创建直到程序结束后才会被销毁。类变量的作用域和实例变量是一样的。它的初始值和成员变量也是一样的,当变量没被初始化的时候根据它的数据类型,会有一个默认值。静态方法是属于类的方法,而不是类对象,它的调用并不作用于类对象,也不需要创建任何的类实例。静态方法本身就是final的,因为重写只会发生在类实例上,静态方法是和类绑定在一起的,不是对象。父类的静态方法会被子类的静态方法屏蔽,只要原来方法没有声明为final。非静态方法不能重写静态方法,也就是说,你不能在子类中把一个静态方法改成实例方法。非静态变量在每一个对象实例上都有单独的一份值。
9、main()方法为什么必须是静态的?
因为main方法是静态的,JVM调用这个方法时就不需要创建任何包含这个main方法的实例。因为C和C++同样有类似的main方法作为程序执行的入口。如果main方法不声明为静态的,JVM就必须创建main类的实例,由于构造器可以被重载,JVM无法确定调用哪个main方法。静态方法和静态数据加载到内存就可以直接调用而不需要像实例方法一样创建实例后才能调用,如果main方法是静态的,那么它就会被加载到JVM上下文中成为可执行的方法。
10、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
11、静态变量在什么时候加载,编译期还是运行期?静态代码块加载的时机呢?
当类加载器将类加载到JVM中时会创建静态变量,并分配内存空间,这跟对象是否创建无关。静态代码块只会在类首次初始化时执行一次。一个类可以有多个静态代码块,它并不是类的成员,无返回值,也不能直接调用。静态代码块不能包含this或者super,它们通常被用初始化静态变量。
12、普通成员方法是否可以访问静态变量?为什么静态方法不能访问成员变量?
普通成员方法(非静态方法)和静态方法都可直接访问调用静态变量.因为它已经创建好。非静态变量需要对象先创建出来后才能访问。
13、switch语句中的表达式可以是什么类型数据?
int、char、byte、short、enmu、string(1.7+支持)
14、while循环和do循环有什么不同?
while循环是先判断再执行,如果判断结构返回的是错误不会执行;
do while循环是不管条件成不成立都先执行一次;
15、什么是finalize()方法?
finalize()是在java.lang.Object里定义的,每一个对象都有这么个方法。
16、finalize()方法什么时候被调用?
finalize()在当垃圾回收器因内存紧张,而去回收某些对象时,会去调用其finalize()方法。一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象。
17、析构函数(finalization)的目的是什么?
finalizetion主要用来释放被对象占用的资源(不是指内存,而是指其他资源,比如文件(File Handle)、端口(ports)、数据库连接(DB Connection)等)。然而它不能真正有效地工作。
1)finalize()的调用事件是不可预知的。
2)事实上没有机制能保证finalize()一定会被调用。
18、final、finally 和 finalize 的区别
final可以用来修饰类,方法和变量(成员变量或局部变量);
final修饰类的时,表明该类不能被其他类所继承。final类中所有的成员方法都会隐式的定义为final方法。
final修饰方法时此方法不能被重写。若父类中final方法的访问权限为private,将导致子类中不能直接继承该方法,因此,此时可以在子类中定义相同方法名的函数,此时不会与重写final的矛盾,而是在子类中重新地定义了新方法。
final成员变量表示常量,只能被赋值一次,赋值后其值不再改变,final修饰一个成员变量(属性),必须要显示初始化。
finally作为异常处理的一部分,它只能用在try/catch语句中,只有与finally对应的try语句块得到执行的情况下,finally语句块才会执行。当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。
finalize()是在java.lang.Object里定义的,每个对象都有这个方法。这个方法在gc启动,该对象被回收的时候被调用。一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象。
19、final与static关键字可以用于哪里?它们的作用是什么?
static:可用于字段,方法,全局变量
1)作用于字段,一个static字段对每个类来说只有一份存储空间,而非static字段是每个对象有一份存储空间。
2)作用于方法,不需要创建任何对象直接调用该static方法。
3)static不能应用于局部变量。
4)Java中禁止使用全局方法,所以引入static方法通过类本身来直接调用。
final:用于变量,方法和类
1)当数据是基本类型时,意味着这是一个永不改变的编译时常量,一个在运行时被初始化的值,不希望它改变。
2)当数据是引用类型时,用static和final修饰表示这是只占据一块不能改变的内存空间。
3)使用final方法的目的就是防止子类对该类方法的覆盖或修改。类中所有private方法都隐式的指定为final。
4)使用final类的目的就是说明我们不打算用任何类继承该类,即不希望该类有子类。
20、能否在运行时向static final类型的赋值?
static修饰的字段在类加载过程中的准备阶段被初始化为0或null等默认值,而后在初始化阶段(触发类构造器)才会被赋予代码中设定的值,如果没有设定值,那么它的值就为默认值。
final修饰的字段在运行时被初始化(可以直接赋值,也可以在实例构造器中赋值),一旦赋值便不可更改;
static final修饰的字段在Javac时生成ConstantValue属性,在类加载的准备阶段根据ConstantValue的值为该字段赋值,它没有默认值,必须显式地赋值,否则Javac时会报错。可以理解为在编译期即把结果放入了常量池中。
21、使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
是引用对象的地址值不能变,引用变量所指向的对象的内容是可以改变。final变量永远指向这个对象,是一个常量指针,而不是指向常量的指针。
22、一个类被声明为final类型,表示什么意思?
final成员变量表示常量,只能被赋值一次,赋值后其值不再改变,final修饰一个成员变量(属性),必须要显示初始化。
23、throws, throw, try, catch, finally分别代表什么意义?
throws表示出现异常的一种可能性,并不一定会发生这些异常;
throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
try-catch-finally结构中try块是必须有的,catch和finally块为可选,但两者至少必须出现其中之一。
24、volatile修饰符的有过什么实践
一种实践是用volatile修饰long和double变量,使其能按原子类型来读写。由于long和double都是64位宽度,因此对这两种类型的读是分为两部分的,第一次读取第一个32位,然后再读剩下的32位,这个过程不是原子的,但volatile型的long或double变量的读写是原子的。
另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。当写一个volatile变量前,Java内存模型会插入一个写屏障(write barrier),读一个volatile变量之前,会插入一个读屏障(read barrier)。就是说,在你写一个volatile域时,能保证任何线程都能看到你写的值,同时在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。
25、volatile变量是什么?volatile变量和atomic变量有什么不同?
volatile变量,轻量级的同步机制,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。在访问volatile变量时不会执行加锁操作,不会使执行线程阻塞。
volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用volatile修饰count变量那么count++操作就不是原子性的。而AtomicInteger类提供的atomic方法可以让这种操作具有原子性如getAndIncrement()方法会原子性的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。
26、volatile类型变量提供什么保证?能使得一个非原子操作变成原子操作吗?
volatile变量提供顺序和可见性保证,例如JVM或JIT为了获得更好的性能会对语句重排序,但是volatile类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。
volatile提供happens-before的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile还能提供原子性,如读64位数据类型,像long和double都不是原子的,但volatile类型的double和long就是原子的。若类中有一个long类型的成员变量,如果该成员变量被多个线程访问,如计数器、价格等,最好将其设置为volatile。因为Java中读取long类型变量不是原子的,需要分成两步,如果一个线程正在修改该long变量的值,另一个线程可能只能看到该值的一半(前 32 位),但是对一个volatile型的long或double变量的读写是原子的。
27、能创建volatile数组吗?
能,不过只是一个指向数组的引用,而不是整个数组,如果改变了引用指向的数组,将会受到volatile的保护,但是如果多个线程同时改变数组的元素,volatile关键字就不能起到保护的作用。
28、transient变量有什么特点?
将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
29、&操作符和&&操作符有什么区别?
短路区别
单&无论左边的结果如何,都会执行右边的操作。
双&&左边为真,右边参与运算;左边为假,右边不再参与运算,直接返回false。
30、a = a + b 与 a += b 的区别?
运算区别:
a += b:先计算a的值,然后用一个temp对象存储,之后和b进行相加,再赋值给a引用。
a = a+b:先计算a + b,再赋值给a引用,如果引用a有计算过程,则会再次计算。
精度区别:
a += b:自动转换类型
a = a+b:需要手动进行强制类型转化。
31、逻辑操作符 (&,|,^)与条件操作符(&&,||)的区别?
位与(&)表示相对应的两位必须都为1,结果才为1,否则为0。
位或(|)表示相对应的每位至少有一个为1,则结果为1,只有两个都为0,结果才为0.
位异或(^)如果两个值不同则为1(如:(1、0)(0、1)),相同(如:(1、1)(0、0))则为0。
逻辑或(||)表示两个值至少有一个为ture,则为true,两个都为false,才为false。
逻辑与(&&)表示两个都为true,结果才为true,否则为false。
32、3*0.1 == 0.3 将会返回什么?true 还是 false?
3*0.1=0.30000000000000004,而4*0.1=0.4
二进制的小数计量精度问题:
任何浮点数可以最多被17位十进制数字表示,如果你转换一个浮点数为十进制字符串需要保留17位数字,这样可以通过这17位数字转换恢复原来的浮点数,这种转换就是round-trip。
Java打印出来的0.1,0.2...0.9是这样的:
Java在程序中计算出的0.1,0.2...0.9,1是这样的:
结论:被打印成长字符串的浮点数比如(0.3,0.8,0.9,1.0)是因为打印出的字符串
(如:0.30000000000000004)是满足round-trip字符串中最短的一个。
33、float f=3.4; 是否正确?
不正确。精度不准确,应该用强制类型转换,float f=(float)3.4 或float f = 3.4f。在java里面,没小数点的默认是int,有小数点的默认是double;
34、short s1 = 1; s1 = s1 + 1;有什么错?
赋值表达式等号两侧的转换的规则是右侧的向左侧的看齐,即右侧表达式要转换到和左边的类型一样。
正确的写法是:short s1=1;s1=(short)(s1+1); 或者 short s1=1;s1+=1;
35、Math.round()什么作用?Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
四舍五入,正数向下取整、负数向上取整;12;-11