【JavaSE笔记】面向对象(四)_接口

本期知识点:

接口
内部类
形式参数和返回值的问题


1. 接口

a. 概述:

动物类中的具体动物,如Cat,Dog。有时候会有额外的动作,如跳高等额外学到的动作。这些动作不能定义到具体类中,所以Java针对这种情况,提供了一个关键字 interface 接口。

b. 接口的定义格式:

i. 类/接口的命名规则:
1) 一个单词:第一个字母大写
2) 多个单词:每个单词的首字母大写
ii. 格式:
interface接口名{
……
}

c. 接口的特点:

i. 方法:
接口里面定义的方法只能是抽象方法★
接口中没有构造方法
ii. 接口子类和接口的关系:
1) 实现关系: implements
子类 implements 接口{
}
2) 抽象的子实现类,没有意义,因为不能实例化。
3) 非抽象的子实现类,是可以实例化的。
4) 需要使用接口的子实现类进行实力化:
AnimalPlay a = new Cat();
例:
				interface AnimalWay{
					public abstract void play();
				}
				abstract class Animal{
					
				}
				class Cat extends Animal {
					
				}
				class PlayCat extends Cat implements AnimalWay{
				
					@Override
					public void play() {
						System.out.println("Cat play ball.");
						
					}
					
				}
				public class Demo01 {
					public static void main(String[] args) {
						AnimalWay a = new PlayCat();
						a.play();
					}
				}
				
				//out:
				Cat play ball.


d. (面试题)接口和抽象类的区别?

i. 成员的区别:
1) 接口:
a) 成员变量:只能是常量,默认的修饰符:public static final。
b) 构造方法:接口中没有构造方法。
c) 成员方法:只能是抽象方法,默认的修饰符:public abstract 。

2) 抽象类:

a) 成员变量:可以常量也可以是变量。
b) 构造方法:可以有有参构造,也可以有无参构造。数据初始化。
c) 成员方法:可以有抽象方法,也可以有非抽象方法。
ii. 关系的区别:
1) 类与类的关系:继承(extends),单继承,不能多继承
2) 接口与接口的关系:继承(extends),可以单继承,也可以多继承
3) 类与接口的关系:实现(implements),可以单实现,也可以多实现。并且一个类继承另一个类的同时可以实现多个接口!
iii. 设计理念的区别:
1) 继承体现的是一种 is a 的关系,由继承保证。
2) 接口体现的是一种like a 的关系,接口多态的一种扩展功能。

例:
			interface Inter{
				int a=10;
				public final int b =20;
				public static final int c =30;
				public abstract void show();
			}
			class A implements Inter{
			
				@Override
				public void show() {
					System.out.println(a);
				}
				
			}
			public class Demo02 {
				public static void main(String[] args) {
					Inter i = new A();
					System.out.println(Inter.a);
					System.out.println(Inter.b);
					System.out.println(Inter.c);//如果一个变量被static修饰,可以使用类名,接口名调用
				}
			}
			//out:
			10
			20
			30

e. 类与类,类与接口,接口与接口之间的关系:

i. 类与类:继承关系。可以单继承,不可以多继承。
ii. 类与接口:继承关系。可以单继承,可以多继承。
iii. 接口与接口:实现关系,可以单实现,也可以多实现,并且继承一个类的同时可以实现多个接口。

f. 猫狗案例(带接口)

猫狗案例,加入玩的额外功能
分析:
猫:姓名,年龄,颜色
有参/无参
成员方法:set()/get(),eat(),eat()
狗:姓名,年龄,颜色
有参/无参
成员方法:set()/get(),eat(),eat()
抽取一个独立类:动物类:抽象类:
有参/无参
成员方法:set()/get()
eat();抽象方法,eat()
猫和狗分别继承自动物类:
部分的猫和狗具有玩功能功能:
定义玩的接口:
部分猫继承自猫 实现玩接口
部分狗继承自猫 实现玩接口
分析:具体到抽象
实现:从抽象到具体
			abstract class Animal2 {
				private String name;
				private int age;
				private String color;
			
				public Animal2() {
					super();
				}
			
				public Animal2(String name, int age, String color) {
					this.name = name;
					this.age = age;
					this.color = color;
				}
			
				public String getName() {
					return name;
				}
			
				public void setName(String name) {
					this.name = name;
				}
			
				public int getAge() {
					return age;
				}
			
				public void setAge(int age) {
					this.age = age;
				}
			
				public String getColor() {
					return color;
				}
			
				public void setColor(String color) {
					this.color = color;
				}
			
				public abstract void eat();
			
			}
			
			interface Playing {
				public abstract void paly();
			}
			
			class Cat2 extends Animal2 {
			
				public Cat2() {
					super();
				}
			
				public Cat2(String name, int age, String color) {
					super(name, age, color);
				}
			
				@Override
				public void eat() {
					System.out.println("Cat eat fish");
				}
			
			}
			
			class Dog2 extends Animal2 {
			
				public Dog2() {
					super();
				}
			
				public Dog2(String name, int age, String color) {
					super(name, age, color);
				}
			
				@Override
				public void eat() {
					System.out.println("Dog eat bone");
				}
			
			}
			
			class PlayCat2 extends Cat2 implements Playing {
			
				public PlayCat2() {
					super();
					// TODO Auto-generated constructor stub
				}
			
				public PlayCat2(String name, int age, String color) {
					super(name, age, color);
					// TODO Auto-generated constructor stub
				}
			
				@Override
				public void paly() {
					System.out.println("This cat like playing ball");
				}
			
			}
			
			class PlayDog2 extends Dog2 implements Playing {
			
				public PlayDog2() {
					super();
				}
			
				public PlayDog2(String name, int age, String color) {
					super(name, age, color);
				}
			
				@Override
				public void paly() {
					System.out.println("This Dog like playing cat");
				}
			
			}
			
			public class 标准动物类带接口 {
				public static void main(String[] args) {
					PlayCat2 a = new PlayCat2("Tom",3,"yellow");
					System.out.println("name:" + a.getName() + " age:" + a.getAge() + " color:" + a.getColor());
					a.eat();
					a.paly();
					Animal2 b = new Cat2("Peter",3,"blue");
					System.out.println("name:" + b.getName() + " age:" + b.getAge() + " color:" + b.getColor());
					b.eat();
					
				}
			}
			//out:
			name:Tom age:3 color:yellow
			Cat eat fish
			This cat like playing ball
			name:Peter age:3 color:blue
			Cat eat fish

2. 内部类

a. 内部类的概述:

在一个类中定义了另一个类,就叫做内部类。
内部类与外部类直接没有继承关系!
例:在A类中定义了一个B类,B就是A类的内部类,A类叫做外部类。

b. 内部类的访问特点:

内部类可以直接访问外部类的成员(包括私有)

c. 外部类可以直接访问内部类的成员吗?

外部类不能直接访问内部类的成员。
需要在这里创建内部类对象,通过内部类对象使用方法。
例:
			class Out01{
				private int a = 10 ;
				
				class In01{
					public void fun(){
				//		内部类可以直接访问外部类的成员,包括私有!
						System.out.println(a);
					}
				}
				public void hun(){
					In01 s = new In01();
					s.fun();
				}
			}
			public class Demo01 {
				public static void main(String[] args) {
					Out01 a = new Out01();
					a.hun();
				}
			}
			//out:
			10

d. 内部类的分类:

i. 成员内部类:在外部类的成员位置。
ii. 局部内部类:在外部类的局部位置。
例:
			class Out{
				private int num = 10 ;
				//成员位置
				//成员内部类
				class In01{
					
				}
				public void fun(){
					//局部位置
					//局部内部类
					class In02{
						
					}
				}
			}

e. 成员内部类:

i. 访问内部类的成员格式:
不能直接创建对象。
格式:
外部类名.内部类名 对象名 = 外部对象.内部对象;
例:
				class Out03{
					private int a = 10 ;
					class In03{
						public void fun(){
							System.out.println(a);
						}
					}
					public void hun(){
						
					}
				}
				
				public class Demo03 {
					public static void main(String[] args) {
					//      格式:外部类名.内部类名 对象名 = 外部对象. 内部类对象;
					//      Out03.In03 a = new Out03().In03();//错误写法
						Out03.In03 a = new Out03().new In03();
						a.fun();
					}
				}

ii. 成员内部类有关的修饰符:
1) 可以有private :目的是保护数据的安全性。
2) 成员内部类可以是一个静态的内部类,静态的内部类访问的外部数据类,必须的静态的。
例:
					class Out04{
						private int a = 10 ;
						private static int b =20;
						
						public static class In04{
							public void fun(){
								System.out.println(b);
							}
							//静态方法
							public static void hun(){
								System.out.println(b);
							}
						}
					}
					public class Demo04 {
						public static void main(String[] args) {
							Out04.In04 a = new Out04.In04();
							a.fun();
							a.hun();
						}
					}

iii. 成员静态内部类访问自己成员的方式
1) 成员内部类被private修饰,那么就不能直接创建对象。
此时静态成员内部类不能用以下的方式访问本类中的成员
Out04.In04 a = new Out04().new In04();//错误方法
2) 如何访问自己内部成员?
a) 成员静态内部类访问内部类成员的访问格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
Out04.In04 a = new Out04.In04();
a.fun();
a.hun();
b) 当成员内部类有一个静态方法fun(),可以用另一种方式访问。
Out04.In04.fun();

f. 局部内部类

i. 局部内部类的成员可以直接访问外部类的数据。
ii. 局部位置访问成员内部类中成员方法,创建局部内部类对象,访问方法。

g. (面试题)局部内部类访问局部变量,有什么要求?

i. 要求:
局部内部类访问局部变量,需要让局部使用final 修饰。
ii. 原因:
局部变量是随着方法的调用而存在的,随着方法调用完毕而消失。但是不会立即消失,等待GC空闲时刻进行垃圾回收,此时fun()方法调用完毕,可是局部本类还在访问,所以,此时就需要将局部使用final 修饰。
例:
				class Out05{
					private int a =10;
					//外部类成员方法
					public void fun(){
						int b =20;		//错误写法
						final int c =30 ;	//正确写法,局部变量必须数常量
						//局部内部类
						class In05{
							public void hun(){
								System.out.println(a);//外部类成员变量
				//			System.out.println(b);//错误
								System.out.println(c);
							}
						}
						//访问hun()方法
						In05 d =new In05();
						d.hun();
					}
				}
				
				public class Demo05 {
					public static void main(String[] args) {
						//创建外部类对象
						Out05 a = new Out05();
						a.fun();
					}
				}

h. 匿名内部类

i. 前提条件:
1) 有一个类或者接口。
2) 这个类可以是具体类/抽象类。
ii. 格式:

new 类名/接口名 ( ){

方法重写;

};
iii. 匿名内部类的本质:
需要继承该类或者实现该接口的子类对象。
例:
			interface Magic{
				public abstract void fun();
				public abstract void hun();
			}
			
			class Out06{
				public void gun(){
					Magic a=new Magic(){
			//一次性调用:接口不能直接实例化:
			//1)创建子实现类型:通过接口多态的形式
			//2)可以使用匿名内部类去访问
			
						@Override
						public void fun() {
							System.out.println("We have fun");
						}
			
						@Override
						public void hun() {
							System.out.println("We have hun");
						}
					};
					a.fun();
					a.hun();
				}
				
			}
			public class Demo06 {
				public static void main(String[] args) {
					Out06 a = new Out06();
					a.gun();
				}
			}
			//out:
			We have fun
			We have hun

i. (面试题):在控制台分别输出:30,20,10

内部类外部类没有继承关系。
使用Outer给限定this。
			class Outer8{
				public int num = 10 ;
				
				//成员内部类
				class Inner8{
					public int num = 20 ;
					
					public void method(){
						int num = 30 ;
						System.out.println(num);
						System.out.println(this.num); //代表当前类的对象:Inner8类中
			//		    System.out.println(new Outer8().num);//使用匿名对象的方式去访问num
						System.out.println(Outer8.this.num);//使用外部累名.this去调用成员变量(外部类限定this)
						
					}
				}
			}
			//测试类
			public class InnerTest2 {
				public static void main(String[] args) {
					//成员内部类访问自己内部成员
					//外部类名.内部类名 对象名 =外部对象.内部类对象 ;
					Outer8.Inner8 oi = new Outer8().new Inner8();
					oi.method();
				}
			}


3. 形式参数和返回值的问题

a. 类作为形式参数:(匿名对象提及过)

		class Student{
			public void show(){
				System.out.println("Good Good Study,Day Day Up");
			}
		}
		class StudentDemo{
			public void method(Student s){
			//s =new Student(); Student s = new Student();
				s.show(); 
			}
		}
		//测试类
		public class StudentTest {
			public static void main(String[] args) {
				//需求:需要调用StudentDemo中method方法
				//1)创建StudentDemo对象
				StudentDemo sd = new StudentDemo() ;
				//2)创建Student类的对象
				Student s = new Student() ;
				//3)将对象名作为参数进行传递
				sd.method(s);
				
				//匿名对象
				new StudentDemo().method(new Student());
			}
		}


b. 抽象类作为形式参数:

抽象类不能直接实例化,就需要抽象类的子类对象。
如下代码,不能直接用 My的对象去调用 hun(),里面的参数是一个抽象类,而抽象类不能直接实例化,所以需要子类进行实例化。
		abstract class Fu{
			public abstract void fun();
		}
		class My {
			public void hun(Fu a){
				a.fun();
			}
		}
		//抽象子类
		class Son extends Fu{
			//重写抽象类的方法
			@Override
			public void fun() {
				System.out.println("I want something just like this!");
			}
			
		}
		public class Demo {
			public static void main(String[] args) {
				/*
				 * 需求:调用My中的hun()方法
				 * 不能直接用My的对象去调用hun(),里面的参数是一个抽象类,而抽象类不能直接实例化,
				 * 所有需要子类进行实例化
				 * */
				My a = new My();
				Fu f = new Son();
				a.hun(f);
			}
		}
		//out:
		I want something just like this!


c. 接口作为形式参数

		//接口
		interface Basic{
			public abstract void fun();
		}
		class Student3{
			//接口也不能直接实例化,只能通过接口多态形式
			public void show(Basic a){
				a.fun();
			}
		}
		//需要创建一个子实现类进行数据的传递
		class Student4 implements Basic{
		
			@Override
			public void fun() {
				System.out.println("I want something just like this!");
			}
			
		}
		public class Demo02 {
			public static void main(String[] args) {
				//需求:调用Student3中的show()方法
				//创建Student3的对象
				Student3 a = new Student3();
				//使用接口多态
				Basic b = new Student4();
				a.show(b);
			}
		}
		//out:
		I want something just like this!

d. 类作为返回值类型

返回的是该类对象

		class People02{
			public void fun(){
				System.out.println("Oh is Magic");
			}
		}
		class PeopleDemo02{
			public People02 hun(){
				return  new People02();
			}
		}
		public class Magic02 {
			public static void main(String[] args) {
				//创建对象
				PeopleDemo02 a = new PeopleDemo02();
				//使用a是PeopleDeom02 对象名
				People02 b = a.hun();
				b.fun();
				//链式编程,一步到位。
				new PeopleDemo02().hun().fun();
			}
		}
		//out:
		Oh is Magic
		Oh is Magic

e. 抽象类作为返回值

返回的不应该是该抽象类的对象(不能实例化),返回的是抽象类的子类对象

		abstract class FuZe{
			public abstract void fun();
		}
		class You{
			public FuZe hun(){
			//	return new FuZe();//错误写法
				return new Sun();//返回的是抽象类的子类对象
			}
		}
		class Sun extends FuZe{
		
			@Override
			public void fun() {
				System.out.println("I want something just like this!");
			}
			
		}
		public class 抽象类作为返回值 {
			public static void main(String[] args) {
				//创建You对象,使用对象去调用成员方法
				You a = new You();
				FuZe b = a.hun();
				b.fun();
				//链式编程
				new You().hun().fun();
			}
		}
		//out:
		I want something just like this!
		I want something just like this!


f. 接口作为返回值

需要返回的是接口的子实现类对象

		interface jieKou{
			public abstract void fun();
		}
		class Student{
			public jieKou getIt(){
				return new Student2();
			}
		}
		class Student2 implements jieKou{
		
			@Override
			public void fun() {
				System.out.println("I want something just like this!");
			}
			
		}
		public class Demo01 {
			public static void main(String[] args) {
				new Student().getIt().fun();
			}
		}
		//out:
		I want something just like this!

g. 总结:★★★

i. 形式参数:
1) 类名:需要该类的对象
2) 抽象类名:需要该类的子类对象
3) 接口名:需要该接口的实现类对象
ii. 返回值类型:
1) 类名:返回的是该类的对象
2) 抽象类名:返回的是该类的子类对象
3) 接口名:返回的是该接口的实现类的对象
iii. 链式编程
1) 对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。







你可能感兴趣的:(Java基础学习)