1. super()与this()的区别?
2. 作用域public,protected,private,以及不写时的区别?
3. 在JAVA中,如何跳出当前的多重嵌套循环?
4. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
5. "=="和equals方法究竟有什么区别?
6. 排序都有哪几种方法?
7. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
8. Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
9. final有什么特点,final的作用?
10. 类的反射
1. super()与this()的区别?
答:(1) 当子类中有和父类中同名的成员变量或者有方法名、参数、返回值类型、访问修饰符都一样的方法时,子类则不能继承这些同名的方法和变量,同时子类也不能继承父类私有的成员变量和方法。若子类中没有和父类同名的变量或者完全一样的方法时,则子类可以通过this.来访问。
(2) 此时this调用这个变量和方法调用的是子类本身的方法和变量,如果要调用父类的同名方法和变量,必须使用super。
(3) 使用super调用父类的构造方法。
当调用子类的构造方法创建实例时,程序会先调用父类的构造方法,但是默认调用的是无参数的构造方法,当父类中的构造方法均为有参数的时候,程序默认调用父类无参构造方法失败且父类的构造方法一定是放在子类构造方法的首位,程序就会报错。
解决办法:(1)在子类构造方法中显示的调用父类有参数的构造方法,并且传递参数给它。
(2)在父类中定义一个无参数的构造方法,以便子类可以调用。
总结:调用子类的构造方法时,一定会在子类的构造方法中先调用父类的构造方法。父类的构造方法有时具有初始化父类功能。
(4) super是在子类中调用父类的东西,this是在同一类中调用其它的成员。
super(参数列表)是调用父类的构造方法。super.是调用父类的成员。
(5) super和this都不能放在static语句块中。
例1:
public class Test{
int a = 10;
public void a(){
System.out.println("parend");
}
}
class T extends Test{
int a = 3;
public void a(){
System.out.println("child");
}
public void b(){
this.a(); //打印值为child
System.out.println(this.a); //打印值为3
System.out.println(super.a); //打印值为10
super.a(); //打印值为parend
}
}
例2:
public class Person {
int a;
public Person(int b){
a = b;
System.out.println("parend");
}
}
class Teacher extends Person{
public Teacher(){
super(5);
}
public void out(){
System.out.println("child");
System.out.println(super.a);
}
}
class T{
public static void main(String[] args) {
Teacher t = new Teacher();
t.out();
}
}
打印结果:parend child 5
2. 作用域public,protected,private,以及不写时的区别?
答:private(私有的)
(1) 只能用在非抽象方法和变量上,不能用在类上(不是类修饰符)。
(2) private所修饰的方法和变量不管在什么情况都只能在本类中使用,在其他类中不能被调用。
public(公共的)
(1) public可以放在类、方法以及变量上,public修饰的类、方法或变量在哪都可以得到调用。
(2) 在一个.java文件中只能有一个public类,但是也可以所有类都不加public。
(3) public修饰的成员变量或方法必须通过对象来访问,除了static修饰的变量或方法可以直接通过类名.方法名/变 量名。
(4) 我们可以把对象访问方法或变量的形式看作对象导航。
default(默认的)
(1) 默认权限的属性或者方法只能在同一个包中使用(非类修饰符),在这个包外的对象是无法访问类的方法和属性。
protected(受保护的)
(1) 和默认的权限其实是一样的。
(2) 在同一个包下的类可以访问受保护的变量和方法。
(3) 不同包下的类继承了另一个包下的类时,则受保护的属性或者方法都会被继承,因此这个类中有了那个类中受保护的方法和属性,但是这只是继承来的,而父类中的那个受保护的方法和属性还是不能被调用,这是对象导航的时候的情况,但是在不同包的子类的方法里可以通过super调用那些受保护的变量和方法。
例:
package a;
public class A
{
protected int a;
}
package b;
import a.A;
public class B extends A
{
public static void main(String args[])
{
B b = new B();
b.a = 1; //这句是可以通过编译,并能正确执行的
A a = new A();
a.a = 1; //这句是不能通过编译的,对象a不能调用其a属性
}
}
3. 在JAVA中,如何跳出当前的多重嵌套循环?
答:
方法一:在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break语 句,即可跳出外层循环。例如,
ok:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(i + " : " + j);
if(i == 4) break ok; //跳出了整个嵌套for循环
}
}
最后打印的一个值为:4 : 0
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(i + " : " + j);
}
if(i == 4) break; //这样也可以跳出整个嵌套循环,但是最后打印的值和上面的不一样
}
最后打印的一个值为:4 : 9
错误写法:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(i + " : " + j);
if(i == 4) break; //这样只是跳出了里面那个for循环,但是外面那个for循环还会接着进行
}
}
最后打印的值为:4 : 0 5 :0 .... 19 : 9
总结:break会直接跳出它直接所在的那个for循环,如果那个for循环外面还有for循环,则会继续执行外面的嵌套循环,如果没有,则直接结束所有循环。
方法二:让外层的循环条件表达式的结果可以受到里层循环体代码的控制,例如,要在二维数组中查找到某个数字。
public void find()
{
int arr[][] = {{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i<arr.length && !found;i++)
{
for(int j=0;j<arr[i].length;j++)
{
System.out.println("i=" + i + ",j=" + j);
if(arr[i][j] == 5)
{
found = true;
break;
}
}
}
}
这里将布尔变量found作为循环能够继续执行的一个条件之一。
4. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
答:(1) 一个.java源文件中可以包括多个类。
(2) 只能有一个public类,而且类名必须和这个.java文件名一样。
5. "=="和equals方法究竟有什么区别?
答:==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this == o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
例:
public class compared {
public static void main(String[] args) {
String a = new String("info");
String b = new String("info");
//a和b是两个不同的变量,而info是这两个变量所只对象内存中所存放的值
String c = "info"; //这里的info是变量c内存中存储的值
String d = "info";
int e = 1;
int f = 1;
System.out.println(a.equals(b)); //true 比较的是a和b两个对象中的内容是否一样
System.out.println(a == b); //false
System.out.println("-----------------");
System.out.println(c.equals(d)); //true
System.out.println(c == d); //true
System.out.println("-----------------");
System.out.println(e == f); //true
System.out.println("-----------------");
T t1 = new T(3,"aaa");
T t2 = new T(3,"bbb");
T t3 = new T(3,"aaa");
System.out.println(t1.equals(t2)); //false
System.out.println(t1.equals(t3)); //false
//为什么都是false,因为我们没有自定义equals方法,所以默认使用了Object的equals方法,而Object方法内部是使用==来比较的,因此此时你比较的永远都是两个变量是否指向同一对象,而这时都为新对象,所以为false。
}
}
疑问:String str = "...";啥意思?
6. 排序都有哪几种方法?
答:冒泡排序,选择排序,插入排序,稀尔排序,快速排序,归并排序,堆排序,基数排序
冒泡排序:相邻之间的数进行交换,每次循环都会找到一个最大或者最小数,则这个数经过多次交换最后被换到最后或最前。
选择排序:相邻之间进行比较,但不会交换,每次比较选取其中的较小或较大值,当经过多次比较到最后的时,就得到了一个最大或 最小值,将这个值替换到数列最前或者最后,直到全部排完。
插入排序:每次插入前,将待插入的那个数与数列中已排好序的数列中的每个数进行比较,当比较到这个数大小介于数列中两个相邻数之间时,则将这个数插入到这两个数中间。
快速排序:在一个待排序的数列中,选择一个数作为基数,比这个数大的放在左边,比这个数小的放在右边,然后又在两边的数中又分别选择两个基数重复开始的操作,直到最后排好序。
7. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
答:round(...)方法是将参数先加0.5,然后求其floor
如:Math.round(-3.8) -3.8+0.5=-3.3然后向下取整为-4
Math.round(3.4) 3.4+0.5=3.9然后向下取整为3
Math.round(3.6) 3.6+0.5=4.1然后向下取整为4
8. Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
答:OverLoad是重载,Override是重写。
重载发生在同一个类中,判断两个方法是不是重载的,最主要的是根据方法名和参数形式,首先,重载和被重载的方法的方法名一定要一样;其次它们一定要具有不同的参数(类型、个数、顺序);最后,它们可以有不同的修饰符和不同的返回值类型,即不能根据返回值类型,访问权限来判断两个方法是不是重载的。
重写(覆盖)在继承关系的两个类中,重写的方法的访问权限一定要比被重载的方法权限要大或相同,而且重载的方法所抛出的异常一定是被重载写方法的子异常或者与之相同。重写的方法一定要有和被重写的方法相同的返回值类型、参数,不同是方法体。
9. final有什么特点,final的作用?
答:(1) final类不能被继承,没有子类,也不能被修改,是最终类,final类中的方法都是final的,final类的属性都是常量,即:赋值一次后就不能再被赋值了。
(2) final方法 :非final类中的final方法可以被继承,但是不能被重写。
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
public class Test4 {
public static void main(String[] args) {
new Test4().f1(2);
}
public void f1(final int i){
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
(3) 作用范围:可以修饰非抽象类,非抽象类的方法和变量,但是不能用来修饰构造方法。
(4) 总结:final修饰的类、方法或变量都是不能改变其内容的,且final类不能被继承,final方法可以继承但不能重写(不能改变)
10. 类的反射
(1) 得到类的Class的对象
i. 对象.getClass()
ii. 类名.class
iii. Class.forName("类的全名")
如果是同一个类或对象得到的Class对象一定是完全一样的。
我的体会:我们通过以上三中方法得到的某个类的Class对象是同一个对象。
例-1:
package com.hhaip.reflect;
public class ClassReflect {
public static void main(String[] args) {
Reflect r1 = new Reflect();
Class c1 = r1.getClass();
Class c2 = Reflect.class;
Class c3 = null;
try {
c3 = Class.forName("com.hhaip.reflect.Reflect");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c1.equals(c2));
System.out.println(c1 == c2);
System.out.println(c1 == c3);
}
}
class Reflect{}
打印结果:true true true
例-2 通过java反射改变一个私有成员变量的值
public class ReflectTest {
@SuppressWarnings("rawtypes")
public static void main(String[] args) throws Exception{
ChangeField cf = new ChangeField();
cf.putStr();
Class clazz = cf.getClass();
Field field = clazz.getDeclaredField("str"); //得到名字为str的这个成员变量
field.setAccessible(true); //让java不要去检查属性的访问权限
field.set(cf, "world"); //给cf这个对象,field这个对象所对应的那个属性赋值
cf.putStr();
}
}
class ChangeField{
private String str = "hello";
public void putStr(){
System.out.println(str);
}
}