一、抽象类
1.1、抽象类概述
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
抽象类特点
抽象类和抽象方法必须用abstract关键字修饰
格式
abstract class 类名 {}
public abstract void eat();
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类不能实例化
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
1.2、抽象类的成员特点
成员变量
可以是变量
也可以是常量
构造方法
有构造方法,但是不能实例化,用于子类访问父类数据的初始化
成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码服用性
public class Test {
public static void main(String[] args) {
Animal a=new Cat();
a.eat();
}
}
abstract class Animal{
abstract public void eat();
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
abstract class Dog extends Animal{
abstract public void eat();
}
1.3、练习
public class Test {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.setName("旺财");
d1.setAge(10);
System.out.println(d1.getName()+"---"+d1.getAge());
System.out.println("=======");
Dog d2 = new Dog(10, "旺财");
System.out.println(d2.getName()+"---"+d2.getAge());
System.out.println("=======");
Animal a1= new Dog();
a1.setName("旺财");
a1.setAge(10);
System.out.println(a1.getName()+"---"+a1.getAge());
System.out.println("======");
Animal a2 = new Dog(10, "旺财");
System.out.println(a2.getName()+"---"+a2.getAge());
}
}
abstract class Animal{
private int age;
private String name;
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
public Animal() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
abstract public void eat();
}
class Cat extends Animal{
public Cat(int age, String name) {
super(age, name);
}
public Cat() {
}
public void eat(){
System.out.println("猫吃鱼");
}
}
class Dog extends Animal{
public Dog(int age, String name) {
super(age, name);
}
public Dog() {
}
public void eat(){
System.out.println("狗吃骨头");
}
}
public class Test2 {
public static void main(String[] args) {
Teacher t= new Basic();
t.age=20;
t.name="张三";
t.teach();
System.out.println(t.name+"---"+t.age);
System.out.println("====");
t=new Work();
t.name="李四";
t.age=30;
t.teach();
System.out.println(t.name+"---"+t.age);
}
}
abstract class Teacher{
String name;
int age;
public abstract void teach();
}
class Basic extends Teacher{
public void teach(){
System.out.println("javaSE");
}
}
class Work extends Teacher{
public void teach(){
System.out.println("javaEE");
}
}
1.4、abstract不能和哪些关键字共存
private 冲突,私有后就不能继承,也就不能重写了
final 冲突 ,同样是不能继承,也就不能重写了
static 无意义,静态方法可以用类名调用,而抽象方法没有方法体,就算能调用也毫无意义。
二、接口
2.1、接口概述
Java中提供了接口来定义额外功能,并不给出具体实现,
接口特点
接口用关键字interface表示
格式:interface 接口名 {}
类实现接口用implements表示
格式:class 类名 implements 接口名 {}
接口不能实例化,但是可以按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
接口的子类
要么是抽象类
要么重写接口中的所有抽象方法
2.2、接口成员特点
成员变量
只能是常量
默认修饰符 public static final
构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
成员方法
只能是抽象方法
默认修饰符 public abstract
public class Test {
public static void main(String[] args) {
AA a=new AAple();
System.out.println(a.num1);
System.out.println(a.num2);
}
}
interface AA{
public static final int num1=20;
public static final int num2=200; //成员变量默认为静态常量
public abstract void show(); //成员方法默认为抽象方法
}
class AAple implements AA{
public void show(){
System.out.println("show");
}
}
2.3、类与类,类与接口以及接口与接口的关系
类与类
继承关系,只能单继承,但是可以多层继承
类与接口
实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口
public class Test2 {
public static void main(String[] args) {
Fu f=new Zi();
f.show();
Mu m=new Zi();
m.show2();
}
}
interface Fu{
public abstract void show();
}
interface Mu{
public abstract void show2();
}
class Zi implements Fu,Mu{
public void show(){
System.out.println("show");
}
public void show2(){
System.out.println("show2");
}
}
接口与接口
继承关系,可以单继承,也可以多继承
public interface Zi extends Fu,Mu {
}
interface Fu{
public abstract void show1();
}
interface Mu{
public abstract void show2();
}
2.4、抽象类和接口的区别
成员区别:
抽象类 变量,常量;有抽象方法;非抽象方法
接口 常量;抽象方法
关系区别:
类与类 继承,单继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
设计理念区别:
抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
2.5、练习
public class Test {
public static void main(String[] args) {
JumpCat jc=new JumpCat();
jc.name="波斯猫";
jc.age=2;
System.out.println(jc.name+"==="+jc.age);
jc.eat();
jc.sleep();
jc.jump();
}
}
interface Jump{
public abstract void jump();
}
abstract class Animal{
String name;
int age;
public abstract void eat();
public void sleep(){
System.out.println("睡觉");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
class JumpCat extends Cat implements Jump{
public void jump(){
System.out.println("跳高猫");
}
}
class JumpDog extends Dog implements Jump{
public void jump(){
System.out.println("跳高狗");
}
}
三、形式参数和返回值问题
3.1、形式参数
基本类型
public class Test {
public static void main(String[] args) {
int num=21;
show(num);
}
public static void show(int a){
System.out.println(a);
}
}
引用类型
类:
public class Test2 {
public static void main(String[] args) {
Student s = new Student();
s.show(s);
}
}
class Student{
public void show(Student s){
System.out.println("show");
}
}
抽象类:
public class Test3 {
public static void main(String[] args) {
new FuDemo().method(new Zi());
}
}
abstract class Fu{
public abstract void show();
}
class Zi extends Fu{
public void show(){
System.out.println("show");
}
}
class FuDemo{
public void method(Fu f){
f.show();
}
}
接口:
public class Test4 {
public static void main(String[] args) {
new FatherDemo().method(new Son());
}
}
interface Father{
public abstract void show();
}
class Son implements Father{
public void show(){
System.out.println("show");
}
}
class FatherDemo{
public void method(Father f){
f.show();
}
}
3.2、返回值类型
基本类型
public class Test2 {
public static void main(String[] args) {
int num1=1;
int num2=2;
int sum = show(num1, num2);
System.out.println(sum);
}
public static int show(int a,int b){
return a+b;
}
}
引用类型
类:
public class Test1 {
public static void main(String[] args) {
new StudentDemo().method().show();
}
}
class Student{
public void show(){
System.out.println("show");
}
}
class StudentDemo{
public Student method(){
return new Student();
}
}
抽象类:
public class Test2 {
public static void main(String[] args) {
new FuDemo().method().show();
}
}
abstract class Fu{
public abstract void show();
}
class Zi extends Fu{
public void show(){
System.out.println("show");
}
}
class FuDemo{
public Fu method(){
return new Zi();
}
}
接口:
public class Test3 {
public static void main(String[] args) {
new FatherDemo().method().show();
}
}
interface Father{
public abstract void show();
}
class Son implements Father{
public void show(){
System.out.println("show");
}
}
class FatherDemo{
public Father method(){
return new Son();
}
}
四、内部类
4.1、内部类概述
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有。
外部类要访问内部类的成员,必须创建对象。
4.2、内部类位置
按照内部类在类中定义的位置不同,可以分为如下两种格式:
成员位置(成员内部类)
class Outer{
class Inner{
}
}
局部位置(局部内部类)
class Outer{
public void show(){
class Inner{
}
}
}
4.3、成员内部类
外界如何创建对象
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
public class Test {
public static void main(String[] args) {
Outer.Inner oi=new Outer().new Inner();
oi.show();
}
}
class Outer{
private int num=10;
class Inner{
public void show(){
System.out.println(num);
}
}
}
4.4、成员内部类的常见修饰符
成员内部的常见修饰符:
1、private 为了保证数据的安全性
2、static 为了让数据访问更方便
被静态修饰的成员内部类只能访问外部类的静态成员
成员内部类被静态修饰后的访问方式是:
格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
4.5、成员内部类的面试题
要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);//30
System.out.println( Inner.this.num);//20
System.out.println( Outer.this.num); //10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
4.6、局部内部类访问局部变量的问题
1、可以直接访问外部类的成员
2、可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
3、局部内部类访问局部变量的注意事项:
必须被final修饰
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。
class Outer{
private int num=100;
public void show(){
final int num2=200;
class Inner{
public void show2(){
System.out.println(num);
System.out.println(num2);
}
}
Inner inner = new Inner();
inner.show2();
}
}
4.7、匿名内部类
就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
new 类名或者接口名() {重写方法;}
本质:
是一个继承了类或者实现了接口的子类匿名对象
public interface Inner {
public abstract void show();
}
class Outer{
public void method(){
new Inner(){
@Override
public void show() {
System.out.println("show");
}
}.show();
}
}
class Test{
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
interface Inner{
public abstract void show1();
public abstract void show2();
}
class Outer{
public void method(){
Inner in= new Inner(){
@Override
public void show1() {
System.out.println("show1");
}
@Override
public void show2() {
System.out.println("show2");
}
};
in.show1();
in.show2();
}
}
4.8、匿名内部类面试题
按照要求,补齐代码
interface Inter {
void show();
}
class Outer {
//补齐代码
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
interface Inter {
void show();
}
class Outer {
public static Inter method(){
Inter in= new Inter(){
@Override
public void show() {
System.out.println("helloworld");
}
};
return in;
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}