天天看点

Java学习笔记(七):抽象类、内部类和匿名内部类

一、抽象类

什么叫抽象方法呢?

在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。

而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。

而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。

只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类

package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:27:32
*/
public abstract class Shape {
	protected String name;
	
	public Shape(String name) {
		this.name=name;
	}
	
	public abstract double perimeter();//求周长
	public abstract double area();//求面积

	@Override
	public String toString() {
		return ("图形为"+name);
	}
}
           

上述代码中,用abstract关键字声明Shape类为抽象类

还定义了两个抽象方法求周长和面积

要注意的是:

抽象类不能直接实例化,因为抽象类存在未实现的方法;

下面来看在Shape类基础上派生出来的Square类

package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:34:19
*/
public class Square extends Shape {
	private double length;
	public Square(double length) {
		super("正方形");
		this.length=length;
	}
	public double getLength() {
		return length;
	}
	public void setLength(double length) {
		this.length = length;
	}
	@Override
	public double perimeter() {
		
		return 4*length;
	}
	@Override
	public double area() {
	
		return length*length;
	}
}
           

再看Rectangle类:

package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:38:51
*/
public class Rectangle extends Shape {

	private double height;
	private double width;
	
	public Rectangle(double height,double width) {
		super("长方形");
		this.height=height;
		this.width=width;
	}
	public double getHeight() {
		return height;
	}
	public void setHeight(double height) {
		this.height = height;
	}
	public double getWidth() {
		return width;
	}
	public void setWidth(double width) {
		this.width = width;
	}
	@Override
	public double perimeter() {
		return 2*width+2*height;
	}
	@Override
	public double area() {
		return width*height;
	}
}
           

再看Circle类:

package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午4:41:39
*/
public class Circle extends Shape {

	private double radius;
	
	public Circle(double radius) {
	super("圆形");
	this.radius=radius;
	}
	public double getRadius() {
		return radius;
	}
	public void setRadius(double radius) {
		this.radius = radius;
	}
	@Override
	public double perimeter() {
		return  2*Math.PI*radius;
	}
	@Override
	public double area() {
		return Math.PI*radius*radius;
	}
}
           

最后给一个Demo类:

package stu.crayue.about_abstract.demo;

import stu.crayue.about_abstract.core.Circle;
import stu.crayue.about_abstract.core.Rectangle;
import stu.crayue.about_abstract.core.Square;

/**
* @author Crayue
* @version 2019年10月31日 下午4:44:09
*/
public class Demo {
	public static void main(String[] args) {
		Square square=new Square(4.0);
		System.out.println(square+"周长:"+square.perimeter());
		System.out.println(square+"面积:"+square.area());
		
		Rectangle rectangle= new Rectangle(3.0, 4.0);
		System.out.println(rectangle+"周长:"+rectangle.perimeter());
		System.out.println(rectangle+"面积:"+rectangle.area());
		
		Circle circle=new Circle(2.0);
		System.out.println(circle+"周长:"+circle.perimeter());
		System.out.println(circle+"面积:"+circle.area());
	}
}

           

运行结果为:

图形为正方形周长:16.0
图形为正方形面积:16.0
图形为长方形周长:14.0
图形为长方形面积:12.0
图形为圆形周长:12.566370614359172
图形为圆形面积:12.566370614359172
           

抽象类编程核心思想:

抽象类由”确定的成分“和”不确定的成分“构成;

”确定的成分“通常由那些类中固定的,固有的和确定的成员、方法构成;

”不确定的成分“是那些类彼此相同,又不同的成分。相同点在于,这些类都存在这些成分;不同点在于,这些成分的具体实现方法不同。

二、内部类

在一个类中,可以定义其他类,这些类称为内部类;

需要注意的是:

1.在内部类的方法中,可以直接引用外部类的所有成员与方法,并且不受权限修饰符的约束;

2.外部类可以定义内部类对象的成员;

给出一个outclass类:

package com.mec.about_inner.core;

public class OuterClass {
	
	private int privateMember;
	protected int protectedMember;
	public int publicMember;
	
	public OuterClass() {
		//这里定义三种不同的权限修饰符的成员
		privateMember = 1;
		protectedMember = 2;
		publicMember = 3;
	}
	
	//这里定义三种不同的权限修饰符的方法
	private void privateFun() {
		System.out.println("privateMember:" + privateMember);
	}
	
	protected void protectedFun() {
		privateFun();
		System.out.println("protectedMember:" + protectedMember);
	}
	
	public void publicFun() {
		privateFun();
		System.out.println("publicMember:" + publicMember);
	}
	
	public class InnerClass {
		private int innerMember;
		
		public InnerClass() {
			innerMember = 4;
		}
		
		private void InnerFun() {
			privateMember++;
			protectedMember++;
			publicMember++;
			
			privateFun();
			protectedFun();
			publicFun();
			System.out.println("innerMember:" + innerMember);
		}
		
	}
	
	//外部类可以定义其内部类对象的成员
	private InnerClass innerObject;
	
	public void fun() {
		//外部类可以实例化该成员,并且可根据内部类的对象,引用内部类的成员和方法
		innerObject = new  InnerClass();
		innerObject.InnerFun();
		System.out.println(innerObject.innerMember++);
	}	
}
           

内部类对应的class文件:

Java学习笔记(七):抽象类、内部类和匿名内部类

额外生成了一个名为“OuterClass$InnerClass”class文件

就表明这个类是在OuterClass类中的内部类InnerClass类

三、匿名内部类

首先给出一个简单的抽象类:

package stu.crayue.about_abstract.core;
/**
* @author Crayue
* @version 2019年10月31日 下午5:28:00
*/
public abstract class Bird {
private String name;
	
	public Bird(String name) {
		this.name = name;
	}
	
	public abstract String cry();
	
	public void print( ) {
		System.out.println( name + "的叫声:" + cry());
	}
}
           

抽象类不能直接实例化,我们试着非实例化下:

package stu.crayue.about_abstract.demo;

import stu.crayue.about_abstract.core.Bird;

/**
* @author Crayue
* @version 2019年10月31日 下午5:29:14
*/
public class Test {

	public static void main(String[] args) {

		Bird jiujiu = new Bird("百灵鸟") {
			@Override
			public String cry() {
				return "啾啾啾啾";
			}
		};
		jiujiu.print();
		
		//第二种手段的展示
		new Bird("嘤嘤怪") {
			@Override
			public String cry() {
				return "嘤嘤嘤";
			}
		}.print();
	}
}
           

实质上我们生成了一个没有机会命名的类,所以这个类为匿名类;

它不能再产生其他对象,但是它会生成相应的类文件;

Java学习笔记(七):抽象类、内部类和匿名内部类

匿名内部类的优点:

1.不需要明确的生成派生类,对于简单问题,明显提高编程效率

2.在需要时临时产生匿名内部类,实现抽象方法,这样更灵活

3.一个匿名内部类对应一种抽象方法的实现,这样更紧凑