【java】第七章、面向对象核心技术

类的封装

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package class_and_object;

public class Cook {
	String name;
	
	public Cook() {
		name = "Jack Chen";
	}
	
	void cutPepper() {
		System.out.println(name + "切辣椒");
	}
	
	void washVegetables() {
		System.out.println(name + "洗蔬菜");
	}
	
	void cooking(String dish) {
		washVegetables();
		cutPepper();
		System.out.println(name + "开始烹饪" + dish);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Cook jack = new Cook();
		
		System.out.println("***请让厨师为我做一份香辣肉丝***");
		jack.cooking("香辣肉丝");
		
		System.out.println("***请问厨师叫什么名字***");
		System.out.println(jack.name);
		
		System.out.println("***请让厨师为我切一份辣椒***");
		jack.cutPepper();
		
	}

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package class_and_object;

public class Cook {
	String name;
	
	public Cook() {
		name = "Jack Chen";
	}
	
	void cutPepper() {
		System.out.println(name + "切辣椒");
	}
	
	void washVegetables() {
		System.out.println(name + "洗蔬菜");
	}
	
	void cooking(String dish) {
		washVegetables();
		cutPepper();
		System.out.println(name + "开始烹饪" + dish);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Cook jack = new Cook();
		
		System.out.println("***请让厨师为我做一份香辣肉丝***");
		jack.cooking("香辣肉丝");
		
		System.out.println("***请问厨师叫什么名字***");
		System.out.println(jack.name);
		
		System.out.println("***请让厨师为我切一份辣椒***");
		jack.cutPepper();	
	}
}

package class_and_object;

public class Waiter {
	Cook jack = new Cook();
	
	void takeOrder(String dish) {
		jack.cooking(dish);
		System.out.println("您的菜做好了,请慢用");
	}
	
	void saySorry() {
		System.out.println("抱歉,餐厅不提供此项服务");
	}

}

package class_and_object;

public class Waiter_Customer {

	public static void main(String[] args) {
		Waiter tom = new Waiter();
		
		System.out.println("***请让厨师为我做一份香辣肉丝***");
		tom.takeOrder("香辣肉丝");
		
		System.out.println("***请问厨师叫什么名字***");
		tom.saySorry();
		
		System.out.println("***请让厨师为我切一份辣椒***");
		tom.saySorry();
	}
}

在这里插入图片描述

类的继承

1、extends关键字

在这里插入图片描述
在这里插入图片描述

package class_and_object;

public class Computer {       //父类:电脑
	String screen = "液晶显示屏";
	
	void startUp() {
		System.out.println("电脑正在开机,请稍等...");
	}
}
package class_and_object;

public class Pad extends Computer{    //子类:平板电脑
	String battery = "5000毫安电池";
	
	void open3G() {
		System.out.println("打开3G网络");
	}
}

package class_and_object;

public class Computer_Pad {

	public static void main(String[] args) {
		Computer com = new Computer();
		Pad ipad = new Pad();
		
		System.out.println(com.screen);
		com.startUp();
		
		System.out.println(ipad.screen);
		ipad.startUp();
		
		System.out.println(ipad.battery);
		ipad.open3G();
		
	}
}

在这里插入图片描述
说明子类可以直接调用从父类那里继承过来的属性和行为

2、方法的重写override

子类与父类完成同一件事,但是它们完成的方法完全不同
在这里插入图片描述

package class_and_object;

public class Computer {       //父类:电脑
	String screen = "液晶显示屏";
	
	void startUp() {
		System.out.println("电脑正在开机,请稍等...");
	}
	
	void showPicture() {
		System.out.println("台式机电脑:用鼠标点击");
	}
}

package class_and_object;

public class Pad extends Computer{    //子类:平板电脑
	String battery = "5000毫安电池";
	
	void open3G() {
		System.out.println("打开3G网络");
	}
	
	void showPicture() {
		System.out.println("平板电脑:用手指点击触摸屏");
	}
}
package class_and_object;

public class Computer_Pad {

	public static void main(String[] args) {
		Computer com = new Computer();
		Pad ipad = new Pad();
		
		com.showPicture();
		ipad.showPicture();
		
	}
}

在这里插入图片描述

3、super关键字

super()关键字的三种用法:调用父类的构造方法、调用父类的属性、调用父类的成员方法
this关键字代表本类对象,super关键字代表父类对象
这个super()也可以调用父类的构造方法,语法同this关键字,同样需要注意的是,我这个构造方法之前不能再写其他的初始化方法
在这里插入图片描述

package class_and_object;

public class Computer {       //父类:电脑
	String screen = "液晶显示屏";
	
	void startUp() {
		System.out.println("电脑正在开机,请稍等...");
	}
	
	void showPicture() {
		System.out.println("台式机电脑:用鼠标点击");
	}
	
	String sayHello() {
		return "欢迎使用";
	}
}

package class_and_object;

public class Pad extends Computer{    //子类:平板电脑
	String battery = "5000毫安电池";
	
	public Pad(){
		super();        //super()必须在最前面
		this.screen = super.screen;
	}
	
	void open3G() {
		System.out.println("打开3G网络");
	}
	
	void showPicture() {
		System.out.println("平板电脑:用手指点击触摸屏");
	}
	
	String sayHello() {
//		return "欢迎使用" + "平板电脑";
		return super.sayHello() + "平板电脑";
	}
}

package class_and_object;

public class Computer_Pad {

	public static void main(String[] args) {
		Computer com = new Computer();
		Pad ipad = new Pad();
		
		System.out.println(com.sayHello());
		System.out.println(ipad.sayHello());
	}
}

在这里插入图片描述

4、注意事项

在这里插入图片描述

多重继承

假如我一个子类又想继承parent1的属性和方法,又想继承parent2的属性和方法,如何解决:多重继承

package class_and_object;

class Parent2{
	void show(){
		System.out.println("我是最顶层的父类");
	}
}

class Parent1 extends Parent2{
	
}

class Child extends Parent1{
	
}

public class Multiple_inheritance {
	
	public static void main(String[] args) {
		// 多重继承
		Child child = new Child();
		child.show();
	}
}

在这里插入图片描述

子类覆盖父类的属性

子类覆盖了父类的属性,子类有一个与父类同名的属性,虽然这俩的名字相同,但是我这么写出来的话, 那就是属于我子类独有的属性

package class_and_object;

class Parent{
	String name;
	public Parent(String name){
		this.name = name;
	}
}

class Child1 extends Parent{
	String name = "Jack";     //虽然与父类的属性同名,但仍然属于子类 独有的属性
	public Child1(String name) {
		super(name);
	}
}

public class Property_with_the_same_name {

	public static void main(String[] args) {
		// 父类 与 子类 有相同名字的属性
		Child1 child = new Child1("tom");
		System.out.println(child.name);
	}
}

在这里插入图片描述
这两个类里的name就完全不是一个东西

object类

在java中,所有的类都会直接或间接地继承object这个类,object类是一个特殊的类,它是所有类的父类,是java中最基层的类
在这里插入图片描述
所有类的超级父类 ,就是这个object类
在这里插入图片描述
在这里插入图片描述

getClass()方法

因为object是所有类的父类,所以object数组可以存放任何一个类的对象
用for each循环输出obj的getClass方法返回对象执行时的Class实例,即我这个类的全名

package class_and_object;

public class GetClass {

	public static void main(String[] args) {
		// 用for each循环输出obj的getClass方法,返回对象执行时的Class实例,即我这个类的全名
		Object arr[] = new Object[4];
		
		arr[0] = new Object();
		arr[1] = new String("字符串");
		arr[2] = new Integer(10);
		arr[3] = new GetClass();
		
		for(Object obj: arr) {
			System.out.println(obj.getClass());
		}
	}
}

在这里插入图片描述

toString()方法

package class_and_object;

public class GetClass {

	public static void main(String[] args) {
		Object arr[] = new Object[4];
		
		arr[0] = new Object();
		arr[1] = new String("字符串");
		arr[2] = new Integer(10);
		arr[3] = new GetClass();
		
		for(Object obj: arr) {
			System.out.println(obj.toString());
		}
	}
}

在这里插入图片描述
第一个它返回的是一个默认值:类名+@+16进制的哈希值
第二个它返回字符串的字面值,因为String这个类重写了这个方法

package class_and_object;

public class GetClass {

	public static void main(String[] args) {
		Object arr[] = new Object[4];
		
		arr[0] = new Object();
		arr[1] = new String("字符串");
		arr[2] = new Integer(10);
		arr[3] = new GetClass();
		
		for(Object obj: arr) {
			System.out.println(obj.toString());
			System.out.println(obj);
		}
	}
	
	@Override
	public String toString() {
		return "我是GetClass类";
	}
}

在这里插入图片描述
其中,由以上两种情况可见,在System.out中,这个toString是可以删掉的,如果我们直接输出这个对象的话,则会自动调用它的toString方法

equals()方法

这个默认的object类的 equals方法, 其实比较的是两个对象的地址是否相等

package class_and_object;

public class GetClass {

	public static void main(String[] args) {
		// 用for each循环输出obj的getClass方法,返回对象执行时的Class实例,即我这个类的全名
		Object arr[] = new Object[4];
		
		arr[0] = new Object();
		arr[1] = new String("字符串");
		arr[2] = new Integer(9);
		arr[3] = new GetClass();
		
		System.out.println(arr[0].equals(arr[3]));     //false
		
		arr[3] = arr[0];
		System.out.println(arr[0].equals(arr[3]));     //true
		
		arr[3] = new Object();
		System.out.println(arr[0].equals(arr[3]));     //false
		
	}
	
	@Override
	public String toString() {
		return "我是GetClass类";
	}
}

在这里插入图片描述
我们通过重写equals方法,就可以自定义地编写我们对象之间的比较规则
在计算机中,(两个对象之间)它默认比较的是计算机的内存地址

package class_and_object;

public class Person {
	String name;
	String id;
	
	@Override
	public boolean equals(Object obj) {
		Person p = (Person) obj;
		boolean b1 = this.name.equals(p.name);
		boolean b2 = this.id.equals(p.id);
		return b1 && b2;
	}
}
package class_and_object;

public class Object_equals {

	public static void main(String[] args) {
		Person p1 = new Person();
		Person p2 = new Person();
		Person p3 = new Person();
		Person p4 = new Person();
		
		p1.name = "小明";
		p1.id = "123";
		
		p2.name = "小红";
		p2.id = "123";
		
		p3.name = "小明";
		p3.id = "456";
		
		p4.name = "小明";
		p4.id = "123";
		
		System.out.println(p1.equals(p2));
		System.out.println(p1.equals(p3));
		System.out.println(p2.equals(p3));
		System.out.println(p1.equals(p4));
		System.out.println(p1 == p4);       //在计算机中,它默认比较的是计算机的内存地址
	}
}

在这里插入图片描述

方法的重载(overload)

方法的重载属于类的多态性的内容之一
在这里插入图片描述
在这里插入图片描述

package class_and_object;

public class Method_Overload {
	static int add(int a) {     //最普通的方法
		return a;
	}
	
	static double add(double b) {     //参数类型不同
		return b;
	}
	
//	如果int add(int a, int b)不存在的话,java无法区分add(int a, double b)和add(double b, int a)该调用哪一个
	static int add(int a, int b) {  //定义与第一个方法参数个数不同
		return a + b;
	}
	
	static int add(int a, double b) {  //参数类型不同
		return (int)(100);
	}
	
	static int add(double b, int a) {  //参数类型不同
		return (int)(-100);
	}
	
	public static void main(String[] args) {
		System.out.println("调用add(int a)方法:" + add(1));
		System.out.println("调用add(double b)方法:" + add(1.1));
		System.out.println("调用add(int a, int b)方法:" + add(1, 2));
		System.out.println("调用add(int a, double b)方法:" + add(1, 2.1));
		System.out.println("调用add(double b, int a)方法:" + add(1.1, 2));
	}
}

在这里插入图片描述

类的上下转型

上:转型方法

子类的对象一定是父类的对象,但是父类的对象不一定是子类的对象了
子类的对象转为父类的对象,就是向上转型父类的对象转为子类的对象,就是向下转型
在这里插入图片描述
在这里插入图片描述

package class_and_object;

public class Person {
	public Person(String name) {
		System.out.println("您好,我叫" + name);
	}
}

package class_and_object;

public class Student extends Person{

	public Student(String name) {
		super(name);
	}
	
	public static void main(String[] args) {
		Person p1 = new Person("tom");
		Person p2 = new Student("jerry");
	}
	
}

在这里插入图片描述
在这里插入图片描述
父类对象 强制转换为 子类对象,这个就是向下转型,向下转型存在一定风险

package class_and_object;

public class Person {
	public Person(String name) {
		System.out.println("您好,我叫" + name);
	}
}
package class_and_object;

public class Doctor extends Person{

	public Doctor(String name) {
		super(name);
	}
}

package class_and_object;

public class Student extends Person{

	public Student(String name) {
		super(name);
	}
	
	public static void main(String[] args) {
		//向上转型 都是正确的
		Person p1 = new Person("tom");
		Person p2 = new Student("jerry");
		Person p3 = new Doctor("jack");
		
//		Doctor dr1 = (Doctor)p1;         //向下转型错误
//		Doctor dr2 = (Doctor)p2;         //向下转型错误
		Doctor dr3 = (Doctor)p3;         //这个向下转型 是正确的
	}
	
}

在这里插入图片描述

下:instanceof关键字

通过上例,我们发现,只有当过医生的人才可以强制转换成医生的对象,而其他人则不可以
我们有没有什么方法 来判断这个人是否可以当医生呢?
instanceof关键字:判断某一个对象是否继承自某一个类
在这里插入图片描述

package class_and_object;

public class Computer_instanceof {    //父类:电脑类
	public static void main(String[] args) {
		PPad ipad = new PPad();
		LenovoPad lenovopad = new LenovoPad();
		Person per = new Person("tom");
		
		System.out.println("Pad是否继承自电脑? " + (ipad instanceof Computer_instanceof));
		System.out.println("lenovopad是否继承自PPad? " + (lenovopad instanceof PPad));
		System.out.println("lenovopad是否继承自电脑? " + (lenovopad instanceof Computer_instanceof));
		System.out.println("ipad是否继承自LenovoPad? " + (ipad instanceof LenovoPad));
		System.out.println("ipad是否继承自Object? " + (ipad instanceof Object));
//		System.out.println("per是否继承自PPad? " + (per instanceof PPad));
	}

}

class PPad extends Computer_instanceof{      //平板电脑类
	
}

class LenovoPad extends PPad{      //联想平板电脑类
	
}

在这里插入图片描述
说明这个instanceof关键字: 他可以判断我是否能继承自父类的父类,就是我的超级父类也可以这么判断,甚至这里可以写Object(所有类的父类)
**反例:**直接报错,因为我这个Pad类和Person类 没有任何继承关系,两个没有任何继承关系的类是不能用instanceof关键字 进行比较的

抽象类

上:抽象类和抽象方法

像颜色这种没有人能说清他长什么样子的,他究竟是什么的类,我们就称它为抽象类
在java中,用abstract这个关键字来对它进行修饰

package class_and_object;

public abstract class Color {
	public void show() {

	}
}

class Red extends Color {
	public void show() {
		System.out.println("我是红色");
	}
}

class Blue extends Color {
	public void show() {
		System.out.println("我是蓝色");
	}
}
package class_and_object;

public class Color_Test {

	public static void main(String[] args) {
		Color c1 = new Red();
		Color c2 = new Blue();
		c1.show();
		c2.show();
		
//		Color c3 = new Color();      //不能创建抽象类的对象
	}
}

在这里插入图片描述
不能创建抽象类的对象。既然它是一个抽象类的对象,那么它就不能进行实例化。若想创建抽象类的对象,必须用它的子类进行实例化
在抽象类中,有一种方法叫做抽象方法,这种方法是只需声明不需实现的
在这里插入图片描述

package class_and_object;

public abstract class Teacher {          //抽象类
	abstract public void teaching();     //抽象方法
}

class MathTeacher extends Teacher{

	@Override
	public void teaching() {               //前面有一个小三角,说明它在实现上面的抽象方法
		System.out.println("这节课我们来讲一下三角函数");
	}
}

class EnglishTeacher extends Teacher{

	@Override
	public void teaching() {               //前面有一个小三角,说明它在实现上面的抽象方法
		System.out.println("open the book");
	}
}
package class_and_object;

public class Teacher_Test {

	public static void main(String[] args) {
		Teacher lee = new MathTeacher();
		Teacher tom = new EnglishTeacher();
		lee.teaching();
		tom.teaching();
	}
}

在这里插入图片描述
在父类老师里,成员方法里什么都没写,但是数学老师和英语老师都继承了老师类,我并没有重写它这个teaching方法,这就导致了我这个数学老师和英语老师也什么都没讲,那这样这个类创建了有什么意义呢
为了避免这样的问题,就出现了抽象方法,用abstract来修饰。这种方法只需声明,不需实现;并且含有抽象方法的类必须是抽象类
上面的例子体现出,这种抽象类必须被继承(不然他就不能被实例化),而这个抽象类里的抽象方法则必须被抽象类的子类所重写(实现)
因为抽象方法没有具体实现,所以每一个子类都必须实现这个抽象方法
在这里插入图片描述

下:抽象类实例

在这里插入图片描述

package class_and_object;

public abstract class Animal {         //动物类
	public Animal(){
		System.out.println("创建了一个动物");
	}
	
	public abstract void eat();    //抽象类中的 抽象方法 只需声明,无需实现
	abstract public void reproduce();
}
package class_and_object;

public abstract class Bird extends Animal{
	String feather;      //羽毛
	
	public Bird(String feather) {
		System.out.println("创建了一个鸟类");
		this.feather = feather;
	}
	
	public void growFeather() {        //还有自己最普通的 成员方法(函数)
		System.out.println("长满" + feather + "羽毛");
	}
	
	abstract public void move();       //这个抽象类里 也有它自己的抽象方法
	
	public void reproduce() {          //前面的小三角表明 这是在实现父类中的抽象方法
		System.out.println("下蛋");
	}
}
package class_and_object;

public class Seagull extends Bird{

	public Seagull(String feather) {
		super(feather);
		System.out.println("我是一只海鸥");
	}

	@Override
	public void move() {
		System.out.println("海鸥飞翔");	
	}

	@Override
	public void eat() {
		System.out.println("海鸥吃鱼");
	}
	
	public static void main(String[] args) {
		Seagull jack = new Seagull("白色");
		jack.eat();
		jack.move();
		jack.growFeather();
		jack.reproduce();
	}
}

package class_and_object;

public class Chicken extends Bird{
	public Chicken(String feather) {
		super(feather);
		System.out.println("我是一只小鸡");
	}

	@Override
	public void move() {
		System.out.println("小鸡快跑");	
	}

	@Override
	public void eat() {
		System.out.println("小鸡吃米");
	}
	
	public static void main(String[] args) {
		Chicken duoduo = new Chicken("黄色");
		duoduo.eat();
		duoduo.move();
		duoduo.growFeather();
		duoduo.reproduce();

	}
}

在这里插入图片描述
在这里插入图片描述

我一个子类继承了抽象类之后,需要实现这个抽象类以及它父类的所有的抽象方法,所以本题弹出了两个需要重写(实现)的抽象方法
因为我这个父类Bird类有有参数的构造方法,所以我要在这里补充一个构造方法
我一个子类实现了父类的所有抽象方法,而且我这个抽象类鸟类也可以实现父类的抽象方法
本题中,用了三层继承关系,小鸡继承了鸟类,鸟类继承了动物类。动物类提供了两个抽象方法,一个是吃一个是繁殖。鸟类提供了一个抽象方法:就是移动move,同时它还提供了一个非抽象方法,还实现了一个父类的抽象方法

接口

在这里插入图片描述
在这里插入图片描述
假如我有这样的需求:我三角形这个类不需要draw方法,那我们就必须把图形类的这个draw方法删掉。但这个方法是一个抽象方法,如果将它删掉,我们就会发现其他子类的draw方法同时消失了
但是我的四边形类和N边形类需要这个方法,怎么办呢?
只能将这个方法写成子类独有的方法,这样的话就不利于我们对这个程序做架构不利于设计这个程序
于是我们引进接口的概念:我们将这个draw方法写到接口中,然后让四边形和N边形这个类来实现这个接口,三角形则不实现。当四边形和N边形实现这个接口的时候,我们就必须将这个draw方法实现
在这里插入图片描述

package class_and_object;

public interface DrawInterface{
	public void draw();
}
package class_and_object;

public class Qua implements DrawInterface{     //四边形简称,四边形类 实现DrawInterface接口

	@Override
	public void draw() {
		System.out.println("绘制四边形");
	}
}
package class_and_object;

public class Square implements DrawInterface{  //正方形类 实现DrawInterface接口

	@Override
	public void draw() {
		System.out.println("绘制正方形");
	}
	
	public static void main(String[] args) {
		DrawInterface d1 = new Qua();   //接口也支持类的向上向下转型
		d1.draw();                      //直接创建接口的对象,然后用它的一个实现类 对它进行实例化
		
		DrawInterface d2 = new Square();
		d2.draw();
	}
}

在这里插入图片描述
接口也支持类的向上向下转型,所以我们这里可以直接创建接口的对象,然后用它的一个实现类 对它进行实例化
我们可以看到,这两个类Qua类和Square类根本没有继承的关系,但是它们同时实现了同一个抽象方法,并不是用抽象类来对它俩进行控制,所以接口用起来很方便

接口的多重继承

与抽象类相比,接口最大的优势就是它能够实现多重继承
接口的多重继承两方面体现:接口继承接口 和 类实现接口
在这里插入图片描述
一个类只能继承一个父类,但是接口不一样,一个类可以实现多个接口

类实现接口(一个类可以实现多个接口)

package multiple_inheritance;

public interface Attack {
	public void shoot();
}

package multiple_inheritance;

public interface Treatment {
	public void treat();
}
package multiple_inheritance;

public class Infantry implements Attack{

	@Override
	public void shoot() {
		System.out.println("步兵进行攻击");
	}
	
}
package multiple_inheritance;

public class Medic implements Attack, Treatment{

	@Override
	public void treat() {
		System.out.println("医务兵治疗他人");
	}

	@Override
	public void shoot() {
		System.out.println("医务兵攻击");
	}

}

package multiple_inheritance;

public class Demo {

	public static void main(String[] args) {
		Infantry tom = new Infantry();
		tom.shoot();
		
		Medic lily = new Medic();
		lily.shoot();
		lily.treat();
	}

}

接口继承接口

package multiple_inheritance;

public interface Attack {
	public void shoot();
}
package multiple_inheritance;

public interface Treatment extends Attack{
	public void treat();
}

package multiple_inheritance;

public class Infantry implements Attack{

	@Override
	public void shoot() {
		System.out.println("步兵进行攻击");
	}
}
package multiple_inheritance;

public class Medic implements Treatment{

	@Override
	public void shoot() {
		System.out.println("医务兵攻击");
	}

	@Override
	public void treat() {
		System.out.println("医务兵治疗他人");
	}

}
package multiple_inheritance;

public class Demo {

	public static void main(String[] args) {
		Infantry tom = new Infantry();
		tom.shoot();
		
		Medic lily = new Medic();
		lily.shoot();
		lily.treat();
	}

}

在这里插入图片描述

接口与抽象类的对比

抽象类和接口都包含了可以由子类 继承实现 的成员,两者有何区别?
在这里插入图片描述
在这里插入图片描述
在接口中,只能声明抽象方法。但是接口可以把abstract关键字省略,默认它也是抽象方法
而在抽象类中,加上abstract关键字就是抽象方法,不加就是非抽象方法(因为抽象类可以有非抽象方法

接口会默认给成员变量添上两个关键字:final static,也就是说,这是一个静态常量,所以不可更改它的值
另外,我可以直接调用interface.id(接口中的静态常量)***
抽象类中的成员变量可以是 任意类型
*(static、final…)

在抽象类中,创建静态代码块和静态方法,它是能够被执行的
(虽然抽象类不能实例化对象,但是他这个静态方法是可用的)
而在接口中,创建静态代码块或者静态方法都会报错,这种语法在接口中不允许出现

package comparision_of_interface_and_abstract_class;

public abstract class Parent1 {
	public Parent1() {
		System.out.println("我们创造了一个抽象类");
	}
	
	String name = "tom";                       //成员变量可以是任意类型
	static public void show() {                //抽象类中可以有静态方法或静态代码块
		System.out.println("这是抽象类的静态方法");
	}
}
package comparision_of_interface_and_abstract_class;

public interface Interface1 {
	int id = 123;            //接口中的成员变量 只能是 静态常量
	public void action();    //接口中的方法 只能是 抽象方法
}
package comparision_of_interface_and_abstract_class;

public interface Interface2 {

}
package comparision_of_interface_and_abstract_class;

public class Demo extends Parent1 implements Interface1, Interface2{

	public static void main(String[] args) {
		Demo d = new Demo();
		d.name = "jack";
		System.out.println(d.name);
		Parent1.show();
	}

	@Override
	public void action() {
		
	}

}

在这里插入图片描述

java类包

在这里插入图片描述
java中的类包有这样一个功能:它相当于一个小容器,我们将一些类放到这个容器中,方便对这些类进行归类整理
在java中,如果我们想要调用一个包中的类,就会用到这样的语法:(这是一个类的完整名称
在这里插入图片描述
我们不能调用两个包下的同名类,因为这样会分不清我在psvm里创建的类是属于哪个包下的(也可以在创建类的时候 使用完整类名
既然java提供了很多包,我们也可以自己来添加包
创建包的命名规则:名字得倒过来写(例如:com.mingri)

package com.mingri;

public class Action {
	public void show() {
		System.out.println("上天");
	}
}
package default_package;

public class Action {
	public void show() {
		System.out.println("入地");
	}
}
package default_package;

//import java.sql.Date;    //一定不能调用两个包下的 同名类
//import java.util.*;

//import java.util.ArrayList;
//import java.util.Date;
//import java.util.List;
//import java.util.*;

public class Demo {

	public static void main(String[] args) {
//		Date date = new Date();
//		List list = new ArrayList();
//		Date date = new Date(1111);
		
		Action a = new Action();
		a.show();
		
		com.mingri.Action b = new com.mingri.Action();
		b.show();
	}

}

在这里插入图片描述

我如果直接导入com.mingri包的话,那我创建对象show()出来的结果就是上天
这就是java类包的效果
它不仅可以将我们的程序分出层次结构(比如不同的类放在不同的包里),它还可以将同名的类进行区分(使用完整的类名就可以区分所有同名类),虽然两个类都叫action,但是创建出来的对象是完全不同的

访问控制

protected:是希望由子类来继承的,其他的和我在同一个包下的类 也能调用
default:控制了只有和我在同一个包内的人 才能使用
private:谁都不许用
在这里插入图片描述

package parent;

public class Parent {
	public void show() {
		System.out.println("Parent向您致敬");
	}
}
package parent;

public class Child extends Parent{
	public void show() {
		super.show();
	}
}
package demo;

import parent.Parent;

public class Demo {

	public static void main(String[] args) {
		Parent p = new Parent();
		p.show();
	}

}

在这里插入图片描述

package parent;

public class Parent {
	protected void show() {    //受保护
		System.out.println("Parent向您致敬");
	}
}
package parent;

public class Child extends Parent{
	public void show() {
		super.show();
	}
}
package demo;

import parent.Child;
import parent.Parent;

public class Demo {

	public static void main(String[] args) {
		Parent p = new Parent();
//		p.show();                  //将Parent类改成protected权限 对其它包中的非子类 不可见 所以会报错
		
		Child c = new Child();
		c.show();                  //将Parent类改成protected权限  对本类所在的包 是可见的
	}

}

在这里插入图片描述

package parent;

public class Parent {
	protected void show() {    //受保护
		System.out.println("Parent向您致敬");
	}
}
package child;

import parent.Parent;

public class Child extends Parent{
	public void show() {
		super.show();
	}
}
package demo;

import child.Child;
import parent.Parent;

public class Demo {

	public static void main(String[] args) {
		Parent p = new Parent();
//		p.show();                  //将Parent类改成protected权限 对其它包中的非子类 不可见 所以会报错
		
		Child c = new Child();
		c.show();                  //将Parent类改成protected权限  对本类所在的包 是可见的
	}

}

在这里插入图片描述
即使我这个子类和我不在同一个包下,因为protected权限对其他包中的子类也是可见的

package parent;

public class Parent {
	void show() {    //缺省
		System.out.println("Parent向您致敬");
	}
}

package child;

import parent.Parent;

public class Child extends Parent{
	public void show() {
		super.show();        //缺省时(这句语句是错误的),其他包中的 子类就访问不到了,不管你和我什么关系,只要我们不在同一个包下,你就不能用我
	}
}
package parent;

public class Parent {
	private void show() {    //私有  只能在本类中使用
		System.out.println("Parent向您致敬");
	}
}
package parent;

public class Child extends Parent{
	public void show() {
	//	super.show();
	}
}

我们发现,即使在同一个包下,你也是我的子类,但是这个show方法仍然不允许你使用
私有方法只有我自己(本类中)可以用

final关键字

这节介绍final关键字***对类的继承的一些 控制的作用***
用到final关键字有三个场景

final类

在这里插入图片描述
被final修饰过的类有一个特点:它不允许有子类(即它不能被继承
在java中,String类和System类就是不允许有子类的
在这里插入图片描述
在这里插入图片描述

final方法

在这里插入图片描述

final常量

在这里插入图片描述
加了final关键字后,这个常量的值就不能再被修改了

内部类

在这里插入图片描述
在这里插入图片描述

成员内部类

外部类不能直接调用成员内部类的成员方法,如果要调用这个方法的话,我们要先创建一个内部类的对象。
这就是外部类方法去调用内部类方法
在main方法中如何创建成员内部类:Demo.innerClass in = d.new innerClass();

package inner_class;

public class Demo {
	innerClass in = new innerClass();
	
	public void outf() {
		in.inf();
	}
	
	class innerClass{     //成员内部类
		int y = 0;
		public innerClass() {
			
		}
		
		public void inf() {
			System.out.println("内部类方法y = " + y);
		}
	}
	
	public static void main(String[] args) {
		Demo d = new Demo();
		d.outf();
		Demo.innerClass in = d.new innerClass();//在main方法中 这样创建 成员内部类 的对象
		in.inf();
	}

}

在这里插入图片描述

局部内部类

我希望我这个s能使用方法中的参数,那如何创建这个内部类的对象呢?
将innerClass2这个类返回,这是会报错的,(因为这个类是在方法体之内声明的,若把这个类返回出去的话,在方法体之外是不存在这个类的)如何解决这个问题?
使用接口来解决这个问题
接口OutInterface专门用来给这个内部类做一个向上转型
我们看到,即使我在构造方法中给它添加了一个值,但是我们获取到的是方法之外的参数x,将这个值传给了s

package inner_class;

public class Demo2 {
	public OutInterface action(String x) {
		class innerClass2 implements OutInterface{   //局部内部类
			public innerClass2(String s) {
				s = x;
				System.out.println(s);
			}
		}
		return new innerClass2("do");
	}
	
	public static void main(String[] args) {
		Demo2 d = new Demo2();
		d.action("局部内部类");
	}

}

interface OutInterface{
	
}

在这里插入图片描述

匿名内部类

我们没有创建任何对象,那就直接return new一个接口OutInterface2(),但是这个接口并不是一个具体的类,所以在这里可以用到匿名内部类
直接实例化这个类,最后需要加分号,大括号之内写的内容就是这个类的类体
这样的写法就是一个匿名内部类,它的效果就相当于以下所示(注释掉的部分):

package inner_class;

public class Demo3 {
	public OutInterface2 action() {
//		return new innerClass2();
		return new OutInterface2() {       //匿名内部类
			private int i = 0;
			public int getValue() {
				return i;
			}
		};
	}
}

interface OutInterface2{
	
}

//class innerClass2 implements OutInterface2{
//	private int i = 0;
//	public int getValue() {
//		return i;
//	}
//}

为什么叫匿名内部类?
因为这个内部类在使用时才对它进行编写

静态内部类

我们发现x这个值 在静态内部类的方法里是不能用的(因为我这个类是静态类,静态的类只能调用静态的属性)
那会有这样一个疑问:它有这么多限制条件,我们为什么还要用它? 因为,它能做到其他类做不到的效果(我们可以在静态内部类中创建main方法
之前我们讲过,主方法只能在主类中运行,而我们这个主方法竟然可以在 主类的静态内部类中运行
内部类有这样一个特点:将其中一个.java文件拷贝到C盘,然后打开控制台(一个java文件生成了两个class文件,因为我们这个代码中有两个类)
静态内部类最大的功能,就是给我们提供一个调试的功能。
将main方法写在静态内部类中,生成class文件之后,因为调试代码在静态内部类中,所以***将该class文件删掉,不会影响我外部类中的代码,仍然可以调用它,这就是静态内部类的特点***

package inner_class;

public class Demo4 {
	int x = 100;
	static class innerClass4{     //静态内部类
//		x = 200;
		public static void main(String[] args) {
			System.out.println("我是静态内部类");
		}
	}
}

在这里插入图片描述

内部类的继承

在这里插入图片描述
在继承内部类的时候,必须要添加一个带参数的构造方法,参数则是我这个外部类的对象;在构造方法中,必须要***调用外部类的它的父类方法(d.super())***,只有这样写,才能为我继承的关系提供必要的对象引用,这种语法是强制的

package inner_class;

public class Demo {
	class innerClass{     //成员内部类
	}
	
	public static void main(String[] args) {
	}
}

class NewClass extends Demo.innerClass{    //内部类的继承
	public NewClass(Demo d) {
		d.super();
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值