一、抽象类
1.1为什么需要抽象类
父类的某些方法,不确定怎么实现,也不需要实现。
class Animal{
public String name;
public Animal(String name){
this.name = name;
}
public void eat()//这里实现了也没有意义
{
System.out.println("这是一个动物,但是不知道吃什么..");
}
}
像上面这个例子,属于一个父类方法不确定性问题,可以考虑将这个方法设计为抽象方法。所谓的抽象方法就是没有实现的方法,没有实现的方法就是没有方法体,当一个类中存在抽象方法时,需要将这个类声明为抽象类。一般来讲,抽象类会被继承,由其子类来实现抽象方法。
1.2抽象类的细节
- 抽象类不能被实例化。
- 抽象类不一定要包含abstract方法,也就是说,抽象类可以没有abstract方法。
- 一旦类包含了abstract方法,那么这个类必须时abstract类。
- abstract只能修饰类和方法,不能修饰属性和其它的。
- 抽象类可以拥有任意成员,抽象类的本质还是类。
- 如果一个类继承了抽象类,则它必须实现抽象类的所有方法,除非它自己也声明为抽象类。
- 抽象方法,不能使用private、final和static来修饰。
二、接口
2.1接口的基本介绍
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。
定义的基本语法:
interface 接口名{
属性
方法
}
调用的基本语法:
class 类名 implements 接口{
自己属性;
自己方法;
必须实现的接口的方法;
}
在JDK7以前,接口中的所有方法都是抽象方法,在JDK7以后的版本中,可以有静态方法和默认方法。另外接口不需要声明为抽象类。
2.2接口的使用细节
- 接口不能被实例化。
- 接口中的所有方法都是public方法,即使没有使用public修饰符,它也是public的。
- 接口中抽象方法,可以不用abstract修饰。
- 一个普通类上实现接口,必须将该接口的所有方法都实现。
- 抽象类实现接口,可以不用实现接口的方法。
- 一个类允许实现多个接口。
- 接口中的属性,只能是final的,而且默认是public static final修饰符。
- 接口中属性的访问形式:接口名.属性名。
- 一个接口不能继承其它类,但是可以继承多个别的接口。
- 接口的修饰符只能是public和默认。
2.3接口与继承
- 继承和接口解决的问题不同:
- 继承的价值在于:解决代码的复用性和可维护性。
- 接口的价值在于:设计好各种规范和方法,让其它类去实现这些方法。
- 接口比继承更加灵活,可以说是对Java单继承方式的一种补充,继承满足is-a关系,接口只需要满足like-a关系。
- 接口在一定程度上实现代码解耦。
2.4接口的多态特性
- 多态参数:接口引用可以指向实现了接口的类的对象。
public class Interface01{ public static void main(String[] args) { IH ih = new A(); IG ig = new A(); } } interface IH{} interface IG{} class A implements IH{}
- 多态数组:多态性允许一个引用类型指向多种实际类型的对象。这种特性在处理数组时尤为有用,因为数组可以存储指向不同子类对象的引用,即使数组的声明类型是父类类型。
- 接口存在多态传递现象
public class Interface01{ public static void main(String[] args) { IH ih = new A(); IG ig = new A(); } } interface IH{} interface IG{} //interface IH extends IG{};A实现IH的同时把IG也实现了 class A implements IH{}
三、内部类
3.1什么是内部类
一个类的内部完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其它类的类被称为外部类。一个内部类:
class Outer{//外部类
private int i = 100;//属性
public Outer(int n1){//构造器
this.i = n1;
}
public void m1(){//方法
System.out.println("m1()");
}
{//代码块
System.out.println("代码块...");
}
class Inner{//内部类
}
}
3.2内部类的分类
定义在外部类局部位置上(比如方法内):
- 局部内部类(没有类名)
- 匿名内部类(没有类名)
定义在外部类的成员位置上:
- 成员内部类(未用static修饰)
- 静态内部类(使用static修饰)
3.3局部内部类
局部内部类定义在外部类的局部位置,比如方法中,并且有类名。
class Outer{//外部类
private int i = 100;//属性
public Outer(int n1){//构造器
this.i = n1;
}
public void m1(){//方法
System.out.println("m1()");
}
{//代码块
System.out.println("代码块...");
}
public void m2(){
class Inner{ //不能添加访问修饰符,因为它是一个局部变量,局部变量不能使用修饰符。
//但是可以用final修饰
public void m3(){
System.out.println(i);//可以直接访问外部类的所有成员,包含私有的。
}
}
Inner i = new Inner();//外部类访问内部类,先创建对象再访问,必须在作用域内。
i.m3();
}
}
总结:
- 内部类可以直接访问外部类的所有成员,包括私有的。
- 外部类访问内部类的成员需要先创建内部类的对象,再访问,并且必须在作用域内部。
- 作用域:仅仅在定义它的方法或者代码块中。
- 除final之外不能使用访问修饰符。
- 局部内部类本质是一个类也可以被继承。
- 如果外部类和内部类的成员重名,默认遵循就近原则,如果想要访问外部类的成员,使用外部类名.this.变量名。
3.4匿名内部类
匿名内部类是定义在外部类的局部位置,没有名字的类(其实有,只不过是由编译器取的,程序员看不见也不能干涉)。
假设我们有一个接口A,内部有一个未被实现的方法eat,如果想要在main中直接调用eat方法,按照传统思路是先用一个类来实现接口A,同时再创建B的对象来调用A。
public class Interface01 {
public static void main(String[] args) {
B b = new B();
b.eat();
}
}
interface A{
public void eat();
}
class B implements A{
@Override
public void eat() {
System.out.println("正在调用eat方法");
}
}
但是,如果这个方法只会实现一次,如果为此单独写一个类还要再创建对象的化,未免有些古板,这里就可以采用匿名内部类。
public class Interface01 {
public static void main(String[] args) {
new A(){
@Override
public void eat() {
System.out.println("正在调用eat方法");
}
}.eat();
}
}
interface A{
public void eat();
}
这是的匿名内部类相当于一个对象,所以它的后面可以直接调用eat方法。当A里面有多个方法时,如果想要同时调用,可以采用下面的方法。
public class Interface01 {
public static void main(String[] args) {
//编译器创建了一个类继承了A类,并且在内部重写了下面这些方法。
//编译类型是A,运行类型是Interface01$1
A a = new A(){
@Override
public void eat() {
System.out.println("正在调用eat方法");
}
public void drink(){
System.out.println("正在调用drink方法");
}
};
a.eat();
a.drink();
}
}
interface A{
public void eat();
public void drink();
}
匿名内部类常用做实参进行传递:
public class InnerClassExercise {
public static void main(String[] args) {
Cellphone cellphone = new Cellphone();
cellphone.alarmlock(new Bell(){
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
Bell innerclass = new Bell(){
@Override
public void ring() {
System.out.println("小伙伴上课了");
}
};
cellphone.alarmlock(innerclass);
}
}
interface Bell{
void ring();
}
class Cellphone{
public void alarmlock(Bell bell){
bell.ring();
}
}
总结:
- 匿名内部类本身既是一个类的定义,也是一个对象,所以从语法上看,它既有定义类的特征,也有创建对象的特征。
- 可以直接访问外部类的所有成员,包含私有的。
- 不能直接添加访问修饰符,因为他的地位就是一个局部变量。
- 作用域:仅仅再定义它的方法内部或者代码块中。
- 外部的其它类不能访问内部匿名类。
- 如果外部类和匿名内部类的成员重名,默认遵循就近原则,也可以通过(外部类名.this.成员名)去访问。
3.5成员内部类
成员内部类是定义再外部类的成员位置,并且没有static修饰。
public class MemberInnerClass01 {
public static void main(String[] args) {
Outer01 outer01 = new Outer01();
outer01.t1();
}
}
class Outer01{
private int a = 10;
public String name = "张三";
class InnerClass{
public void say()
{//可以直接访问外部类的成员
System.out.println("Outer01的a = " + a + "\tOuter01的name + " + name);
}
}
public void t1(){
InnerClass innerClass = new InnerClass();
innerClass.say();
}
}
总结:
- 可以直接访问外部类的所有成员,包含私有的。
- 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位是一个成员。
- 作用域:和外部域的其他成员一样,为整个类体比如前面案例。在外部类的成员方法中创建成员内部类对象,再调用方法。
- 成员内部类访问外部类成员:直接访问。
- 外部类访问成员内部类:先创建对象,再访问。
外部其它类访问成员内部类:
- 可以依托这样的语法:
OuterClass.InnerClass inner = OuterClass.new InnerClass()
- 在外部类中编写一个方法返回一个成员内部类的对象。
public class MemberInnerClass01 {
public static void main(String[] args) {
Outer01 outer01 = new Outer01();
Outer01.InnerClass inner01 = outer01.new InnerClass();
inner01.say();
Outer01.InnerClass inner02 = outer01.getInnerClass();
inner02.say();
}
}
class Outer01{
private int a = 10;
public String name = "张三";
class InnerClass{
int a = 20;
public void say()
{
System.out.println("Outer01的a = " + a + "\tOuter01的name + " + name);
}
}
public InnerClass getInnerClass(){
return new InnerClass();
}
}
3.6静态内部类
静态内部类定义在外部类的成员位置,并且有static修饰。
public class StaticInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
//使用固定的语法
Outer.Inner inner1 = new Outer.Inner();
inner1.say();
System.out.println("----------");
//编写一个函数,返回静态内部类的对象实例
Outer.Inner inner2 = outer.getInner();
inner2.say();
System.out.println("----------");
//静态函数版本
Outer.Inner inner3 = Outer.getInner_();
inner3.say();
}
}
class Outer {
private int n1 = 10;
private static int n2 = 20;
public static class Inner{//可以添加访问修饰符
public void say(){
//System.out.println(n1);//报错,不能访问非静态成员
System.out.println(n2);//正确。
}
}
public Inner getInner(){
return new Inner();
}
public static Inner getInner_() {//静态版本
return new Inner();
}
}
总结:
- 可以直接访问外部类的所有静态成员,包含私有的,但是不能直接访问非静态成员。
- 可以添加任意访问修饰符,因为它的低位就是一个成员。
- 作用域:等同于其他成员,为整个类体。
- 静态内部类访问外部类:直接访问。
- 外部类访问静态内部类:创建对象在访问。
- 外部其它类访问静态内部类:
- 使用语法进行访问:
Outer.Inner inner1 = new Outer.Inner();
- 编写一个函数,返回内部类的一个对象。函数可以有static版本。
- 使用语法进行访问:
- 当与外部类成员重名时,采用外部类名.成员来访问。
标签:内部,对象,void,接口,class,new,JavaSE,public From: https://blog.csdn.net/qq_55890817/article/details/144146446