四种访问修饰符:
这篇文章写的很好:java中的访问修饰符
protected重点突出继承,只要是子类,就算再不同得包中也可以访问
default重点突出包,只能在相同得包中的类才可以访问
内部类:
内部类特点:
- 内部类可以直接访问外部类成员,包括私有
- 外部类需要访问内部类成员,必须创建对象,可以在外部类中创建一个方法,然后方法里创建内部类对象调用内部类成员
- 外部类.内部类名 对象名 = 外部类对象.内部类对象( Outer.Inner oi = new Outer().new Inner() )
- 静态内部类,因为之前说了,可以直接用类名访问静态类里面得方法,所以:外部类.内部类名 对象名 = 外部类名.内部类对象,也就是( Outer.Inner oi = new Outer.Inner() )
- 私有内部类:对于成员内部类得私有使用,private,只能被当前类的方法访问,所以可以在外部类创建一个方法,创建内部类对象然后使用内部类方法
- 内部类获取外部类成员,采用 外部类名.this.外部类成员
- 局部内部类:定义在类的方法中的类,局部内部类在访问他所在的方法中的局部变量时必须用finnal修饰,因为方法结束后就弹栈了,变量也弹出去了,但是类还在堆里,还要用到变量,所以加个finnal将变量放到方法区常量池里(jdk1.8不需要加finnal了,如果加了finnal就有bug了,但我认为这就是个不好的改变)
- 匿名内部类:也是局部内部类的一种,必须写在方法里,本质是一个继承了该类(一般是抽象类)或者实现了该接口的子类匿名对象,匿名内部类最好只针对只有一个方法的接口或者类,有固定的格式(具体代码测试看最下面):
new 接口名/类名(){
重写方法
}.方法名
局部内部类内存图:
下面写个代码测试一下上述属性(静态内部类、私有内部类、局部内部类):
public class LongTest {
public static void main(String[] args) {
//静态static内部类测试
Outer.Inner1 oi1 = new Outer.Inner1();
oi1.say();
//私有private内部类测试:私有内部类就不能像下面的普通内部类一样直接创建对象访问了(显示not visible)
//要在外部类里创建方法访问内部类成员,就像类的私有属性只能本类方法调用一样
Outer o2 = new Outer();
o2.outerPrint();
//普通内部类测试:访问内部类成员需要创建对象
Outer.Inner3 oi3 = new Outer().new Inner3();
oi3.eat();
//普通内部类测试:内部类获取外部类成员,采用 外部类名.this.外部类成员
oi3.outereat();
}
}
class Outer{
int num = 10;
public void eat() {
System.out.println("Outer吃饭啊_内部类调用外部内方法测试");
}
//静态static内部类
static class Inner1{
public void say() {
System.out.println("说话啊_静态static内部类测试");
}
}
//私有private内部类
private class Inner2{
public void print() {
System.out.println(num);
}
}
public void outerPrint() {
Inner2 i2 = new Inner2();
i2.print();
}
//普通内部类
class Inner3{
public void eat() {
System.out.println("Inner3吃饭啊_普通内部类测试");
}
//内部类获取外部类成员,采用 外部类名.this.外部类成员
public void outereat() {
Outer.this.eat();
}
}
}
输出:
局部内部类的代码(关键是在外部类的方法里就要创建内部类的对象,外部类方法才能调用内部类方法):
public class LongTest {
public static void main(String[] args) {
Outer out = new Outer();
out.method();
}
}
class Outer{
public void method() {
int num = 10;
class Inner{
public void print() {
System.out.println(num);
}
}
Inner i = new Inner();
i.print();
}
}
匿名内部类代码测试:
public class LongTest {
public static void main(String[] args) {
Outer out = new Outer();
out.method(new Animal() {
public void sleep() {
System.out.println("sleep_开发中匿名内部类对象当作方法的参数");
}
});
out.interfaceTest();
}
}
//抽象类
abstract class Animal{
public abstract void sleep();
}
//接口
interface Jump{
public abstract void jump();
}
class Outer{
public void method(Animal a) {
a.sleep();
}
public void interfaceTest() {
new Jump() {
public void jump() {
System.out.println("jump_接口匿名内部类测试");
}
}.jump();
}
}
输出:
并且,匿名内部类也可以作为返回值返回:
public class LongTest {
public static void main(String[] args) {
Outer.method().show(); // Outer.method()返回一个子类对象,这个里面返回Inter对象
// Inter i = Outer.method();
// i.show();
}
}
interface Inter{
public abstract void show();
}
class Outer{
public static Inter method() {
return new Inter() {
public void show() {
System.out.println("fffff");
}
};
}
}