引文:
本文将涉及Java中abstract关键字,接口和内部类的语法与细节~
一、abstract
1.1案例引入
需求:现在我们要设计一个Person类一个工作方法,然后让Student类和Teacher类继承Person类,在Student类和Teacher类中重写Person类的工作方法.
public class test {
public static void main(String[] args) {
}
}
class Person{
public void work(){
System.out.println();
}
}
class Student extends Person{
@Override
public void work() {
System.out.println("学生正在上课~");
}
}
class Teacher extends Person{
@Override
public void work() {
System.out.println("老师正在教书~");
}
}
此时我们发现Person类中的work()方法该写啥呢?貌似写啥都不对,很尴尬。
此时,我们可以将这个方法声明为抽象方法!
于是我们在方法前面加上abstract关键字。
翻译:在非抽象中抽象方法
所以说当一个类中存在抽象方法是,也需要将这个类声明为抽象类!
由于这个抽象方法你不知道咋写,所以语法规则也让你不要再写方法体了!
1.2 abstract使用语法
用abstract来修饰一份类时,这个类为抽象类
用abstract来修饰一份方法时,这个类为抽象方法 注意:抽象方法没有方法体!
抽象类的价值在于让子类继承并实现抽象方法
1.3 abstract使用细节
抽象类不能实例化,即你不能创建抽象类对象
抽象类可以没有抽象方法,但抽象方法一定在抽象类中
abstract只能修饰类和方法,不能修饰属性
如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非自己声明为抽象类(打不过就加入)
抽象方法不能是用private、final、static来修饰,与重写相违背
private: 私有方法无法被子类访问,谈嘛重写呢
final:本来就是为了不让重写才加的
static: 本来写static是为了能用类来直接调用,而abstract是为了让子类重写,而且抽象方法没有方法体,所以从语法层根本不让你过。
二、接口
2.1接口VS抽象类
接口的使用也是为了重写方法。
这不是跟抽象类的使用差不多吗?有啥区别呢?有抽象类不就够了吗
抽象类也是继承,只是明确了某些方法必须重写,根本还是为了解决代发的复用性和可维护性
接口更强调设计方法,让其他类去实现这些方法
抽象类是继承,满数的关系:is - a, 而接口值只满足 like - a
举个例子:坤坤是个人,所以他可以继承Person类,他会唱跳rap篮球,这些是他后天学习得来的,用接口来实现更合理
2.2基本介绍与语法
介绍:接口就是给出一些没有实现的方法(抽象方法),封装到一起,某个类要使用的时候,再实现出来。
语法:
interface MyInterface{ //接口
//属性
//方法
//1.抽象方法 2.默认实现方法 3.静态方法
}
class A implements MyInterface{
//必须实现接口的抽象方法
}
注意:Jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
2.3接口使用细节
接口不能被实例化(与抽象类类似)
接口中所有的方法都是public的和abstract的,如果你没写,会自动认为。
如果一个普通类implements了接口,就必须将接口中所有的抽象方法实现。
抽象类implements了接口,可以不用实现接口的方法
一个类可以implements多个接口
接口中的属性会被默认为public static final
接口不能继承其他类,但能继承接口
三、内部类
3.1基本介绍
简单来说就类套类,是类的五大成员(属性、方法、构造器、代码块、内部类)
class Outer{ //外部类
class Inner{//内部类
}
}
3.2局部内部类
局部内部类就是放在外部类的方法中的类
显然局部内部类可以访问外部类中所有成员,包括私有的,因为属于本类
那外部内如何访问局部内部类呢?
public class InnerClass{
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun();
}
}
class Outer{ //外部类
public void fun(){//方法
class localInner{//局部内部类
public void say(){
System.out.println("你好,我是内部局部类~");
}
}
localInner localInner = new localInner();
localInner.say();
}
}
在含有局部内部类的方法中创建对象调用方法,在main方法中再创建外部类的对象调用方法。
注意:当外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用
外部类.this.成员
3.3匿名内部类
匿名内部类就是没有名字的局部内部类
语法:
new 类或接口(参数列表){
};
public class Test {
public static void main(String[] args) {
new Person(){
@Override
public void say() {
System.out.println("我是匿名内部类~");
}
}.say();
}
}
class Person{
public void say(){
System.out.println("Hello~");
}
}
甚至我们还能这样调用!
public class Test {
public static void main(String[] args) {
Speak speak = new Speak(){
public void say(){
System.out.println("嘻嘻~");
}
};
speak.say();
}
}
interface Speak{
public void say();
}
乍一看,咦,这不是接口实例化了吗?其实并没有,但是匿名内部类在作用
我们先看speak这个引用,他的编译类型为Speak,那运行类型呢?就是匿名内部类!
我们可以通过getclass这个方法看到他的“名字”
所以本质上是这样的:Speak speak = new Test$1 implements Speak;
类似于继承中的向上转型。
应用:
需求:假设我们现在想要养一只小狗,我们可以立马命令小狗做事。
class Dog{
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void Doing(Order order){
order.action();
}
}
interface Order{
public void action();
}
如果我们不适用匿名内部类的话,我们每要让小狗做一个事情,就需要实现一个类来实现接口,很麻烦。
但是我们可以使用匿名内部类来简化代码。
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("小黄");
dog.Doing(new Order() {
@Override
public void action() {
System.out.println("小狗汪汪叫~");
}
});
dog.Doing(new Order() {
@Override
public void action() {
System.out.println("小狗去睡觉~");
}
});
}
}
对于第四行本质上:Order order = new Test$1 implements Order
由于重写,会执行{}内中action的方法。
十分方便,对于只是用一次的方法可以写成匿名内部类的形式。
3.4成员内部类
成员内部类是定义在外部类的成员位置上
特点:
可以直接访问外部类中的所有成员(私有也可以)
可以添加访问修饰符(private....),因为他的地位就是一个成员
外部其他类访问成员内部类
方法1:
public class Test {
public static void main(String[] args) {
AAA aaa = new AAA();
AAA.BBB bbb = aaa.new BBB();
bbb.say();
}
}
class AAA{
class BBB{
public int n1 = 10;
public void say(){
System.out.println("你好~");
}
}
}
aaa.new BBB()相当于 把 new BBB()当做是aaa的成员
方法2:
public class A {
public static void main(String[] args) {
AAA aaa = new AAA();
AAA.BBB b = aaa.getBBB();
}
}
class AAA{
class BBB{
public int n1 = 10;
public void say(){
System.out.println("你好~");
}
}
public BBB getBBB(){
return new BBB();
}
}
让这个类返回就行
3.5静态成员内部类
在成员内部类前加上static
特点:
只能访问外部类的所有静态成员,非静态成员不可访问
可以添加访问修饰符(private....),因为他的地位就是一个成员
外部其他类访问成员内部类
public class A {
public static void main(String[] args) {
AAA.BBB b = new AAA.BBB(); //不同于非静态的创建
b.say();
}
}
class AAA{
static class BBB{
public int n1 = 10;
public void say(){
System.out.println("你好~");
}
}
public BBB getBBB(){
return new BBB();
}
}
因为是静态的,可以直接通过类名直接访问.
本人是java小白,如有问题请指出。