-
面向对象的特征有哪些?
封装、继承、多态
封装: 封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。**在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。**通常情况下,只要记住让变量和访问这个变量的方法放在一起,将一个类中的成员变量全部定义成私有的,只有这个类自己的方法才可以访问到这些成员变量,这就基本上实现对象的封装,就很容易找出要分配到这个类上的方法了,就基本上算是会面向对象的编程了。把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中。
继承: 在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。
多态: 多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。 -
访问修饰符 public、protect、private及不写的区别?
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
修饰符 | 当前类 | 同包 | 子类(同一包) | 子类(不同包) | 其他 |
---|---|---|---|---|---|
public | V | V | V | V | V |
protected | V | V | V | V/X | X |
defualt | V | V | V | X | X |
private | V | X | X | X | X |
注:protected
-
子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
-
子类与基类不在同一包中:那么在子类中,子类实例可以通过this访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
- String 是最基本的数据类型吗?
不是 - float f=3.4;是否正确?
不正确 - short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
- short在运算过程中会被提升到int类型或者更高类型进行运算。这是由于Java会自动将short数据在运算过程中当作一个int类型的字面值(literal)进行处理。byte类型做运算时同样如此,会被java自动进行提升等级。
- java语言规范中关于复合赋值的解释是这样的:E1 op=E2等价于
E1=(T)(E1 op E2),这里的T是E1的数据类型,看到这里 ,大家应该豁然开朗了,原来这个复合赋值是自带了隐式的强制类型转换的。 - 精度小于int的数值运算的时候都回被自动转换为int后进行计算;
-
Java有没有goto?
goto是java语言中的保留字,目前还没有在java中使用。 -
int和Integer有什么区别?
Integer是int的包装类;int是基本数据类型;
Integer变量必须实例化后才能使用;int变量不需要;
Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
Integer的默认值是null;int的默认值是0。
详细描述 -
&和&&的区别?
两者都可以做逻辑与运算。
& 同时还是按位与运算符
逻辑运算区别:
& 作为逻辑运算时两边的表达式都要执行(| 逻辑或一样);
&& 为短路运算符(|| 逻辑或一样),如果左边表达式为false,右边表达式不再执行;只有左边为true时,右边表达式才执行。 -
解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。
- 堆区:专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中)
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身.
3.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。 - 栈区:对象实例在Heap 中分配好以后,需要在Stack中保存一个4字节的Heap内存地址,用来定位该对象实例在Heap 中的位置,便于找到该对象实例。
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
4.由编译器自动分配释放 ,存放函数的参数值,局部变量的值等. - 静态区/方法区:
1.方法区又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
3.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
-
Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
Math.round(11.5)=12
Math.round(-11.5)=-11
Math.floor(11.5)=-11
Math.floor(-11.5)=-12 -
switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
switch 语句中的变量类型可以是: byte、short、int 、char、String(Java7+开始支持) -
用最有效率的方法计算2乘以8?
2<<3 -
数组有没有length()方法?String有没有length()方法?
数组有length属性,String有length()方法 -
在Java中,如何跳出当前的多重嵌套循环?
- 方法一:
要跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体代码中使用带标号的break语句,即可跳出外层循环。例如:
tag: for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
System.out.println("i="+i+", j="+j);
if(j==5) break tag;
}
}
- 方法二:
让外层的循环条件表达式的结果可以受到里层循环体代码的控制,例如:
boolean flag = true;
for (int i = 0; i < 10 && flag; i++) {
for (int j = 0; j < 10; j++) {
System.out.println("i=" + i + ", j=" + j);
if (j == 5) {
flag = false;
break;
}
}
}
- 方法三:
使用return返回。
-
构造器(constructor)是否可被重写(override)?
Constructor(构造器)不能被继承,所以不能被override(重写),但是可以被overloading(重载)。 -
两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
对,因为hashcode函数可以被重写。 -
是否可以继承String类?
不可以,因为String 被final修饰 -
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
Java中方法参数只有值传递 -
String和StringBuilder、StringBuffer的区别?
- 执行速度
StringBuilder > StringBuffer > String
我们知道String是字符串常量,不可变对象,因此每次对String进行操作的时候实际上是生成了一个新的String对象,然后将指针指向新的String对象上,之前的String对象就没有了指针引用,当内存中无引用的对象多了之后,就会触发JVM的GC操作了。
StringBuilder和StringBuffer是字符串变量,因此当我们对字符串做操作的时候,实际上都是操作的同一个对象,不会创建新的对象。
注意:
String str="hel"+"lo";
String a = "hel";
String b ="lo";
String c = a+b;
上面的两部分代码虽然输出的结果都是“hello”,但是在jvm中的内存分布是完全不同的。
String str=“hel”+“lo”; 中的str是一个编译时常量,最后分配到内存里面的只有"hello" 这一款内存区域。
而下面的三行代码,则需要在内存中分配三块地址,【“hel”,“lo”,“hello”】。
由此可以得出执行顺序了,但是StringBuilder为什么会比StringBuffer快呢,请继续往下看
-
线程安全
StringBuilder是线程不安全的,而StringBuffer是线程安全的
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append(“le”) 会使字符串缓冲区包含“startle”,而 z.insert(4, “le”) 将更改字符串缓冲区,使之包含“starlet”。
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。 -
总结
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
- 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
-
重载(Overload):首先是位于一个类之中或者其子类中,具有相同的方法名,但是方法的参数不同,返回值类型可以相同也可以不同。
(1)方法名必须相同
(2)方法的参数列表一定不一样。
(3)访问修饰符和返回值类型可以相同也可以不同。 -
重写(override):一般都是表示子类和父类之间的关系,其主要的特征是:方法名相同,参数相同,但是具体的实现不同。
重写的特征:
(1)方法名必须相同,返回值类型必须相同
(2)参数列表必须相同
(3)访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
(4)子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
(5)构造方法不能被重写,因为不可以被继承
-
描述一下JVM加载class文件的原理机制?
a. 装载:查找和导入class文件;
b. 连接:
① 检查:检查载入的class文件数据的正确性;
② 准备:为类的静态变量分配存储空间;
③ 解析:将符号引用转换成直接引用(这一步是可选的)
c. 初始化:初始化静态变量,静态代码块。
这样的过程在程序调用类的静态成员的时候开始执行,所以静态方法main()才会成为一般程序的入口方法。类的构造器也会引发该动作。 -
char 型变量中能不能存贮一个中文汉字,为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。