Java学习----(5)

面向对象(下)

接口:(提高可扩张性和可维护性)

定义:

[修饰符] interface 接口名 extends 父接口1 , 父接口2 ...
{
    零个到多个常量定义...
    零个到多个抽象方法定义...
    零个到多个内部类、接口、枚举定义...
    零个到多个默认方法或类方法定义...
}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16    

定义一个接口:

package lee;
public interface Output
{
	//接口里定义的成员变量只能是常量
	int MAX_CACHE_LINE=50;
	//接口里定义的普通方法只能是public的抽象方法
	void out();
	void getData(String msg);
	//在接口中定义默认方法,需要使用Default修饰
	default void print(String... msgs)
	{
		for(var msg :msgs)
		{
			System.out.println(msg);
		}
	}
	//在接口中定义默认方法,需要使用default修饰
	default void test()
	{
		System.out.println("默认的test()方法");
	}
	//在接口中定义类方法,需要使用static修饰
	static String staticTest()
	{
		return "接口里的类方法";
	}
	//定义私有方法
	private void foo()
	{
		System.out.println("foo私有方法");
	}
	//定义私有静态方法
	private static void bar()
	{
		System.out.println("bar私有静态方法");
	}
}
package yeeku;
public class OutputFieldTest
{
	public static void main(String[] args)
	{
		//访问另一个包中的Output接口的MAX_CACHE_LINE
		System.out.println(lee.Output.MAX_CACHE_LINE);
		//下面语句将引发“为final变量赋值”的编译异常
		//lee.Output.MAX_CACHE_LINE = 20
		//使用接口来调用类方法
		System.out.println(lee.Output.staticTest());
	}
}

接口的继承:

接口的继承和类继承不一样,接口完全支持多继承。(一个接口可以有多个直接父接口。)

子接口扩展某个父接口,将会获得父接口里定义的所有抽象方法、常量。

使用接口:

[修饰符] class 类名 extends 父类 implements 接口1 , 接口2 . . .
{
    类体部分
}

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_14,color_FFFFFF,t_70,g_se,x_16

 接口和抽象类:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

一个系统的接口不应该经常改变,一旦接口被改变,对整个系统甚至其他系统的影响将是辐射式的,导致系统中大部分类都需要改写。

 面向接口编程:

命令模式:

假设有一个方法需要遍历某一个数组的数组元素,但无法确定在遍历数组元素时如何处理这些元素,需要在调用该方法时指定具体的处理行为。

用Command接口来定义一个方法,用这个方法来封装“处理方法”。

public interface Command
{
    //接口里定义的process方法用于封装“处理行为”
    void process(int[] target);
}

在这个处理类中包含一个process()方法

public class ProcessArray
{
    public void process(int[] target , Command cmd)
    {
        cmd.process(target);
    }
}

 通过一个Command接口,就实现了让ProcessArray类和具体“处理行为的分离,程序使用Command接口代表了对数组的处理行为。

public class CommandTest
{
	public static void main(String[] args)
	{
		ProcessArray pa = new ProcessArray();
		int[] target = {3,-4,6,4};
		//第一次处理数组,具体处理行为取决于PrintCommand
		pa.process(target , new PrintCommand());
		System.out.println("----------------");
		//第二次处理数组,具体处理行为取决于AddCommand
		pa.process(target , new AddCommand());
	}
}

PrintCommand类:

public class PrintCommand implements Command
{
	public void process(int[] target)
	{
		for(int tmp : target )
		{
			System.out.println("迭代输出目标数组的元素:" + tmp);
		}	
	}
}

AddCommand类:

public class AddCommand implements Command
{
	public void process(int[] target)
	{
		int sum = 0;
		for(int tmp : target)
		{
			sum += tmp;
		}
		System.out.println("数组元素的总和是: " + sum);
	}
}

结果:

102231dc0e124c7b93a82a84568e86f6.png

 内部类:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

非静态内部类:

内部类定义语法格式如下:

public class OuterClass
{
    //此处可以定义内部类
}

 同一个Java源文件里可以定义多个类,那种情况不是内部类,它们依旧是两个互相独立的类:(内部类一定是放在另一个类的类体部分定义)

//下面A,B两个空类互相独立,没有谁是谁的内部类
class A{}
public class B{}

Java不允许在非静态内部类里定义静态成员。

非静态内部类里面不能有静态方法、静态成员变量、静态初始化块。

 

静态内部类:

外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员。

使用内部类:(定义类的主要作用就是定义变量、创造实例和作为父类被继承。定义内部类的主要作用也如此)

1、在外部类内部使用内部类:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

2、在外部类以为使用非静态内部类:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

在外部类以外的地方定义内部类(包括静态和非静态两种)变量的语法格式如下:

OuterClass.InnerClass varName

在外部类以外的地方创建非静态内部类实例的语法如下:

OuterInstance.new InnerConstructor()

 非静态内部类的构造器必须使用外部类对象来调用

3、在外部类以外使用静态内部类。

创建静态内部类实例的语法如下:

new OuterClass.InnerConstructor()

为静态内部类StaticIn类定义一个空的子类:

public class StaticSubClass extends StaticOut.StaticIn()

匿名内部类:

定义格式:

new 实现接口() | 父类的构造器(实参列表)
{
    //匿名内部类的类体部分
}

必须且只能继承一个父类,或实现一个接口

匿名内部类的两条规则:

1、匿名内部类不能是抽象类;

2、匿名内部类不能定义构造器。

 Lambda表达式:

Lambda表达式的代码块将会代替实现抽象方法的方法体,Lambda表达式相当于一个匿名方法;

Lambda表达式的主要作用就是代替匿名内部类的繁琐语法。它由三部分组成:

1、形参列表。形参列表允许省略形参类型。如果形参列表只有一个参数,甚至连形参列表的圆括号也可以省略;

2、箭头(->);

3、代码块。

 Lambda表达式与函数式接口:

Lambda表达式的两个限制:

1、Lambda表达式的目标类型必须是明确的函数式接口;

2、lambda表达式只能为函数式接口创造对象。Lambda表达式只能实现一个方法,因此它只能为一个抽象方法的接口(函数式接口)常见对象。

 

为了保证Lambda表达式的目标类型是一个明确的函数式接口,可以由如下三个常见操作:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_19,color_FFFFFF,t_70,g_se,x_16

 枚举类:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

 枚举类都继承了Java.lang.Enum类

java.lang.Enum类中提供了如下几个方法:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa3VrdWRlWVNC,size_20,color_FFFFFF,t_70,g_se,x_16

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kukudeYSB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值