java常见问题
一些java常见问题
java常见问题
一、 Java 内部类
内部类有四种常见的类型:成员内部类、局部内部类、匿名内部类和静态内部类。
1.成员内部类:定义为另一个类的里面如下:
class Circle { double radius = 0;
public Circle(double radius) { this.radius = radius;
}
class Point{ //内部类
public void DrawPoint() {
System.out.println("DrawPoint");
}
}
}
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问。
同时需要注意当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
2.局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
class People{ public People() {
}
}
class Man{ public Man(){
}
public People getWoman(){ class Woman extends People{ //局部内部类
int age =0;
} return new Woman();
}
}
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
3.匿名内部类
大部分匿名内部类用于接口回调。常见于各种监听响应这些的代码当中。如下:
scan_bt.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) { // TODO Auto-generated method stub }
});
4.静态内部类
静态内部类也是定义在另一个类里面的类,但是在类的前面多了一个关键字static。它是不需要不需要依赖于外部类的,它可以因为在没有外部类的对象的情况下,可以创建静态内部类的对象,也因此它不能使用外部类的非static成员变量或者方法。
public class Test { public static void main(String[] args) {
Outter.Inner inner = new Outter.Inner();
}
}
class Outter { public Outter() {
}
static class Inner { public Inner() {
}
}
}
5.为什么局部内部类和匿名内部类只能访问局部final变量?
如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值,这样就会出现数据不一致的情况的发生
二、 Java访问控制符
1.private(当前类访问权限):如果类里的一个成员(包括成员变量、方法和构造器等)使用private访问控制符来修饰,则这个成员只能在当前类的内部被访问。很显然,这个访问控制符用于修饰成员变量最合适,使用它来修饰成员变量就可以把成员变量隐藏在该类的内部。
2.protected(子类访问权限):如果一个成员(包括成员变量、方法和构造器等)使用protected访问控制符修饰,那么这个成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问。在通常情况下,如果使用protected来修饰一个方法,通常是希望其子类来重写这个方法。
3.public(公共访问权限):这是一个最宽松的访问控制级别,如果一个成员(包括成员变量、方法和构造器等)或者一个外部类使用public访问控制符修饰,那么这个成员或外部类就可以被所有类访问,不管访问类和被访问类是否处于同一个包中,是否具有父子继承关系。
4. Java 泛型:
什么是Java泛型:通俗的讲,泛型就是操作类型的 占位符,即:假设占位符为T,那么此次声明的数据结构操作的数据类型为T类型。
为什么要使用泛型?其实就是为了 类型安全,List<String> 就是用来操作String类型的,你插入Person对象就不行。但是在编译之后会去掉泛型类型。
5. Java 中,直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容,比较内容请用String.equals()。
6. Java的常量池放在方法区。
7. join方法 wait方法 notify方法
现假设有一块钟表对象,钟表有两个线程,一个是查询当前时间,另一个是将时间显示出来。需要显示出正确的时间。
由于线程之间的竞争关系,导致很多次显示时间的线程先执行,而获取时间的线程后执行,不能显示正确的时间。这个时候就可以用join,wait,notify 方法。
1.join方法的特点:执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再继续向下执行
显示时间的线程执行join方法,而获取时间的线程调用join方法,因此显示时间的线程会等待获取时间的线程执行完再执行,从而可以保证每次都可以获得正确的时间。
2.对象锁调用了wait()方法会使当前持有该对象锁的线程处于线程等待状态同时该线程释放对对象锁的控制权,直到在其他线程中该对象锁调用notify()方法或notifyAll()方法时等待此对象锁的线程才会被唤醒。需要注意wait方法是一个本地方法,其底层是通过一个叫做监视器锁的对象来完成的。所以在调用wait方式时要获取到monitor对象的所有权,那如何获取monitor对象所有权?Java中只能通过Synchronized关键字来完成。
8. Java类初始化的顺序:
1.非继承关系中的初始化顺序:static静态代码块和静态成员 -> 普通成员 -> 构造函数执行
2.继承的子类:父类静态代码块和静态成员 -> 子类静态代码块和静态成员 ->父类普通成员和非static块 -> 父类构造函数 -> 子类普通成员和非static块 -> 子类构造函数 。
9. 抽象类和接口:
抽象类是用来捕捉子类的通用特性的 。它不能被实例化。抽象方法可以继承一个类和实现多个接口。子类使用extends关键字来继承抽象类。
接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。且接口方法默认修饰符是public。你不可以使用其它修饰符。接口只可以继承一个或多个其它接口。子类使用关键字implements来实现接口。
10. Java的final 关键字:
1.修饰类当用final去修饰一个类的时候,表示这个类不能被继承。注意:a. 被final修饰的类,final类中的成员变量可以根据自己的实际需要设计为fianl。b. final类中的成员方法都会被隐式的指定为final方法。
2.被final修饰的方法不能被重写:a. 一个类的private方法会隐式的被指定为final方法。b. 如果父类中有final修饰的方法,那么子类不能去重写。
3.修饰成员变量,必须要赋初始值,而且是只能初始化一次。