一.Java中的内部类:
1.内部类的定义:
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。
成员内部类:
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。
例:
class Test1{
private String data = "外部属性";
class Inner1{
private String data = "内部属性";
public void print(){
System.out.println("成员内部类");
System.out.println(Test1.this.data);
System.out.println(data);
}
}
}
这段代码里Inner1就是Test1的内部类。
外部类要去访问内部类时需要注意的是在访问内部类时需要先实体化外部类对象,然后再在实体化的外部类对象中对内部类进行一个实体化。然后才能进行访问。
例:
Test1 test1 = new Test1();//实例化外部类对象
test1.new Inner1().print();
//在外部类实例化的对象内实例化一个内部类,然后去调用其方法
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以“外部类类名.this.成员变量/成员方法”
局部内部类:
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
例:
class Test2{
private String data = "外部属性";
public void func(){
class Inner2{
private String data = "内部属性";
public void print(){
System.out.println("局部内部类");
System.out.println(Test2.this.data);
}
}
new Inner2().print();
}
}
注意:注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的!
局部内部类的访问:
例:
Test2 test2 = new Test2();
test2.func();//因为函数当中有类的实例化方法故不需要我们再去实例化内部类
静态内部类:
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
例:
class Test3{
private String data = "外部属性";
static class Inner3{
public void print(){
System.out.println("静态内部类");
}
}
}
静态内部类的访问:
Test3.Inner3 inner3 = new Test3.Inner3();
inner3.print();
这段代码表示静态内部类也有着静态属性共有特征:不需要实例化,可以直接用类名调用即可访问。
匿名内部类:
匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件,内部类必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
匿名内部类的注意事项:
1.匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
2.匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块。
匿名内部类的特征:
一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。
但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。
例:
class Test4{
new Inner4(){
@Override
public void print() {
System.out.println("匿名内部类");
}
}.print();
//new操作符后的“()”后跟的是“{}”内的实现方法,最后的“.”调用了实现的类里边的方法
}
Test4 test4 = new Test4();
//输出结果“匿名内部类”
二.Java中的抽象类:
抽象类就是不能使用new方法进行实例化的类,即没有具体实例对象的类。抽象类有点类似“模板”的作用,目的是根据其格式来创建和修改新的类。
对象不能由 抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子类来创建对象。当一个类被声明为抽象类时,要在这个类前面加上修饰符abstract。
抽象方法:
抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。
注意:抽象方法只能出现在抽象类中!
抽象类中不一定包含抽象方法,但是包含抽象方法的类一定要被声明为抽象类。抽象类本身不具备实际的功能,只能用于派生其子类。抽象类中可以包含构造方法, 但是构造方法不能被声明为抽象。
注意:抽象类不能用final来修饰,即一个类不能既是最终类又是抽象类。abstract不能与private、static、final、native并列修饰同一个方法。
例:
abstract class Shape{
private String type;
public abstract double countPerimeter();
public abstract double countArea();
protected Shape(String Type){
this.type = type;
}
public String getType(){
return this.type;
}
}
构造函数用protected修饰的原因:抽象类的构造函数只有一个作用,就是在派生类中使用,所以一般用protected去修饰
抽象类一般被用于继承,抽象类既可以被抽象类继承,也可以被非抽象类继承,但是被非抽象类继承的时候要注意把抽象类中的所有抽象方法都要进行一次重写。
例:
class Recantangle extends Shape{
private double length;
private double width;
public Recantangle(String type, double length, double width) {
super(type);
this.length = length;
this.width = width;
}
@Override
public double countPerimeter() {
return 2 * (this.length + this.width);
}
@Override
public double countArea() {
return this.length * this.width;
}
}
在实际运用中,抽象类通常被用来作为模板,然后以抽象类为父类去根据不同的需求去定义不同的子类,这种工作方法通常被称为模板模式。
来源:CSDN
作者:水里一条老咸鱼
链接:https://blog.csdn.net/qq_44997197/article/details/103205547