java基础个人笔记之抽象类,接口与多态,内部类

抽象类:
抽象:笼统,模糊,看不懂!不具体。

特点:
1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
抽象方法必须定义在抽象类中。该类必须也被abstract修饰。
2,抽象类不可以被实例化。为什么?因为调用抽象方法没意义。
3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。
否则,这个子类还是抽象类。

1,抽象类中有构造函数吗?
有,用于给子类对象进行初始化。

2,抽象类可以不定义抽象方法吗?
可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
通常这个类中的方法有方法体,但是却没有内容。

3,抽象关键字不可以和那些关键字共存?
private 不行
static 不行
final 不行

4,抽象类和一般类的异同点。
相同点:
抽象类和一般类都是用来描述事物的,都在内部定了成员。
不同:
1,一般类有足够的信息描述事物。
抽象类描述事物的信息有可能不足。
2,一般类中不能定义抽象方法,只能定非抽象方法。
抽象类中可定义抽象方法,同时也可以定义非抽象方法。
3,一般类可以被实例化。
抽象类不可以被实例化。

5,抽象类一定是个父类吗?
是的。因为需要子类覆盖其方法后才可以对子类实例化。

abstract class AbsDemo
{
	abstract void show1();
	abstract void show2();
}

当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用
另一种形式定义和表示,就是 接口 interface。

//定义接口使用的关键字不是class,是interface.
对于接口当中常见的成员:而且这些成员都有固定的修饰符。
1,全局常量: public static final (修饰符不写会自动补全)
2,抽象方法。public abstract

由此得出结论,接口中的成员都是公共的权限.

interface Demo
{
	public static final int NUM = 4;
	public abstract void show1();
	public abstract void show2();
}

//类与类之间是继承关系,类与接口直接是实现关系。
接口不可以实例化。
只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。
否则,这个子类就是一个抽象类。

class DemoImpl implements /*实现*/Demo
{
	public void show1()
	{}
	public void show2()
	{
	}
}

在java中不直接支持多继承,因为会出现调用的不确定性。
所以java将多继承机制进行改良,在java中变成了多实现。
一个类可以实现多个接口。 接口的出现避免了单继承的局限性。

抽象类和接口的异同点:
相同点:
都是不断向上抽取而来的。
不同点:
1,抽象类需要被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2,抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。
接口中只能定义抽象方法,必须由子类去实现。
3,抽象类的继承,是is a关系,在定义该体系的基本共性内容
接口的实现是 like a 关系,在定义体系额外功能
例子:犬按功能分:有导盲犬,搜爆犬。

abstract class 犬 //基本功能
{
	abstract void 吼叫();
}
interface 导盲   //额外功能
{
	abstract void 导盲();
}
class 导盲犬 extends 犬 implements 导盲
{
	public void 吼叫()
	{
	}
	public void 导盲(){}
}

对象的多态性。

class 动物
{}

class 猫 extends 动物
{}

class 狗 extends 动物
{}


猫 x = new 猫();

动物 x = new 猫();//一个对象,两种形态。

猫这类事物即具备者猫的形态,又具备着动物的形态。
这就是对象的多态性。

简单说:就是一个对象对应着不同类型.

多态在代码中的体现:
父类或者接口的引用指向其子类的对象。

多态的好处:
提高了代码的扩展性,前期定义的代码可以使用后期的内容。

多态的弊端:
前期定义的内容不能使用(调用)后期子类的特有内容。

多态的前提:
1,必须有关系,继承,实现。
2,要有覆盖。

毕老师和毕姥爷的故事。

class 毕姥爷
{
	void 讲课()
	{
		System.out.println("管理");
	}
	void 钓鱼()
	{
		System.out.println("钓鱼");
	}
}

class 毕老师 extends 毕姥爷
{
	void 讲课()
	{
		System.out.println("Java");
	}
	void 看电影()
	{
		System.out.println("看电影");
	}
}

class  DuoTaiDemo2
{
	public static void main(String[] args) 
	{
//		毕老师 x = new 毕老师();
//		x.讲课();
//		x.看电影();

		毕姥爷 x = new 毕老师();//多态,自动类型提升,老师对象提升了姥爷类型。但是只能访问毕姥爷的方法(外部看到的是毕姥爷(本身是毕老师),若毕姥爷和毕老师有方法一样,使用的是毕老师的方法),无法使用毕老师特有的方法。
		//作用就是限制对特有功能的访问。
		//专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。

		x.讲课();
		x.钓鱼();
		
		毕老师 y = (毕老师)x;//如果想用毕老师的特有功能,你可以将该对象进行向下转型。
		//向下转型的目的是为了使用子类中的特有方法。
//		注意:对于转型,自始自终都是子类对象在做着类型的变化。
		y.看电影();
	}
}

//a instanceof People//instanceof:用于判断对象的具体类型。只能用于引用数据类型判断 //通常在向下转型前用于健壮性的判断。

多态时
成员的特点:
1,成员变量。
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。

2,成员函数(非静态)。
编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。

因为成员函数存在覆盖特性。

3,静态函数。
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。

	其实对于静态方法,是不需要对象的。直接用类名调用即可。

内部类访问特点:
1,内部类可以直接访问外部类中的成员。
为什么内部类能直接访问外部类中成员呢?
那是因为内部类持有了外部类的引用。 外部类名.this
2,外部类要访问内部类,必须建立内部类的对象。

一般用于类的设计。
分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。
这时就是还有的事物定义成内部类来描述。

class InnerClassDemo
{
	public static void main(String[] args) 
	{
//		Outer out = new Outer();
//		out.method();
		//直接访问外部类中的内部类中的成员。
//		Outer.Inner in = new Outer().new Inner();
//		in.show();

		//如果内部类是静态的。 相当于一个外部类
//		Outer.Inner in = new Outer.Inner();
//		in.show();

//static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的。
//如果内部类是静态的,成员也得是静态的。
//		Outer.Inner.function();
		
	}
}

内部类可以存放在局部位置上。
内部类在局部位置上只能访问局部中被final修饰的局部变量。

class Outer
{
	int num = 3;
	Object method()
	{

		final int x = 9;

		class Inner
		{
			public String toString()
			{
				return "show ..."+x;//内部类在局部位置上只能访问局部中被final修饰的局部变量。
			}
		}

		Object in = new Inner();
		return in;//0x0045
//		in.show();
	}


	
}

class InnerClassDemo3 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		Object obj = out.method();
		System.out.println(obj);
	}
}
/*

class Fu extends Object
{}
class zi extends Fu
{}

Fu f = new zi();

Object o = new Fu();

匿名内部类。就是内部类的简写格式。

必须有前提:
内部类必须继承或者实现一个外部类或者接口。

匿名内部类:其实就是一个匿名子类对象。

格式:new 父类or接口(){子类内容}
通常的使用场景之一:
当函数参数是接口类型时,而且接口中的方法不超过三个。
可以用匿名内部类作为实际参数进行传递

class Outer
{
	void method()
	{
		/*new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		}.show()//运行通过;*/
		
		Object obj = new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		};
		obj.show();//因为匿名内部类这个子类对象被向上转型为了Object类型。
					//这样就不能在使用子类特有的方法了。obj没有show方法
	}
}

class InnerClassDemo6 
{
	public static void main(String[] args) 
	{
		new Outer().method();
	}
}

实例化对象运行的顺序::首先执行构造函数中默认的super()父类初始化父类=》然后初始化当前对象=》最后执行构造函数中的代码

猜你喜欢

转载自blog.csdn.net/qq_43630812/article/details/84428129