JAVA继承:
子类凭什么叫父类爹?因为写了extends
子类实例化的时候访问父类中的构造函数
在子类构造对象时,发现访问子类构造函数时,父类也运行了,为什么呢?
原因:在子类的构造函数中第一行有一个默认的隐式语句。super();
子类的实例化过程:子类中所有构造函数默认都会访问父类中的空参数的构造函数。
为什么子类实例化的时候要访问父类中的构造函数呢?
那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前
要先看父类是如何对自己的内容进行初始化的。
所以子类在构造对象时,必须访问父类中的构造函数。
如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确调用父类中的那个构造函数
父类中哪个构造函数,同时子类构造函数中如果使用this调用了本类构造函数时
那么super就没有了,因为super和this都只能定义第一行,所以只能有一个,但是可以保证的是子类中肯定会有其它的构造函数访问父类的构造函数。
注意:super语句必须要定义在子类构造函数的第一行。因为,你是儿子他是爸爸
JAVA中支持单继承,不支持多继承,但对C++中的多继承机制进行了改良。
单继承:一个子类只能有一个直接父类
多继承:一个子类可以有多个直接父类(java中不允许,进行改良了)
在java中是通过“多实现”的方式来进行展现的(有关什么是多实现,之后的文章中会提到)
为什么不直接支持多继承?
不直接支持,是因为多个父类中有相同成员,会产生调用的不确定性。
java 支持多层(多重)继承: C继承B,B继承A
就会出现继承体系
当要使用一个继承体系时:
1、查看该体系中的顶层类,了解该体系的基本功能。
2、创建体系中的最子类对象,完成功能的使用。
在子父类中,成员的特点体现
1、成员变量
2、成员函数
3、构造函数
成员变量
当本类中的成员和局部变量同名用this区分
当子父类中的成员变量同名用super区分
this和super的用法很相似
this:代表一个本类对象的引用
super:代表一个父类空间
final关键字(把值固定住):
final 可以修饰类,方法,变量
final 修饰的类不可以被继承
final修饰的方法不可以被覆盖
final修饰的变量是一个常量,只能被赋值一次
内部类只能访问被final修饰的局部变量
重载
它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。
public class Parent{//定一个类
public void read(){
}
public void show(){//重载了show方法
}
public void show(int a){//重载了show方法,比第一个方法多了一个参数
}
}
覆盖
当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作。这时函数在子父类中的特性。
函数两个特性:
1,重载。同一个类中。overload
2,覆盖。子类中。覆盖也称为重写,覆写。override
覆盖注意事项:
1,子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
2,静态只能覆盖静态,或被静态覆盖。
什么时候使用覆盖操作?
当对一个类进行子类的扩展时,子类需要保留父类的功能声明
但是要定义子类中该功能的特有的内容时,就要使用覆盖操作完成。
子类继承父类,然后子类声明和父类一样的某个方法,方法里面的内容将父类方法内容覆盖
(保留父类的某个功能,但是改变功能的内容)
抽象类
抽象的概念:笼统,模糊,看不懂!不具体
特点:
1、方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰
抽象方法必须定义在抽象类中,该类必须也被abstract修饰
2、抽象类不可以被实例化(不能创建对象),为什么?
答:因为调用抽象方法没有意义
3、抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化,否则这个子类还是抽象类
因为:如果没有覆盖,这个子类中继承父类(抽象类)之后,还含有抽象类,抽象类必须要定义在抽象方法中,所以这个子类还是抽象类。
5个问题:
1、抽象类中有构造函数吗?
有,用于给子类对象进行初始化。
2、抽象类可以不定义抽象方法吗?
可以的。但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
通常这个类中的方法有方法体(判断有没有方法体,看有没有大括号),但却没有内容。
3、抽象关键字不可以和哪些关键字共存?
private 不行(抽象需要被覆盖,你他妈的隐藏起来了咋覆盖)
static 不行(如果抽象成员变静态,不需要对象,抽象方法运行毫无意义啊,连方法体都没有运行啥?)
final 不行 (抽象要被覆盖,你final抽象方法,咋覆盖)
4、抽象类和一般类的异同点。
相同点:
抽象类和一般类都是用来描述事务的,都在内部定义了成员。
不同:
1、一般类有足够的信息描述事务
抽象类描述事物的信息有可能不足
2、一般类中不能定义抽象方法,只能定义非抽象方法
抽象类中可定义抽象方法,同时也可以定义非抽象方法
3、一般类可以被实例化
抽象类不可以被实例化
5、抽象类一定是个父类吗?
是的。
设计模式——对问题行之有效的解决方式。其实它是一种思想
1、单例设计模式
解决的问题:就是可以保证一个类在内存中的对象唯一性。
必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
如何保证对象唯一性呢?(解决办法:我不让你new,我来new,我就new一个,然后对外提供方法获取该对象)
1、不允许其他程序用new创建该类对象。
2、在该类创建一个本类实例。
3、对外提供一个方法让其他程序可以获取该对象。
class Single
{
static Single s = new Single ();
private Single (){}
//私有化对象
public static Single getInstance()
{
//此处可以加一些判断条件,满足条件,才能用这里的这个对象(为了可控)
return s;
}
}
class SingleDemo
{
public static void main (String[] args)
{
//Single ss =Single.getInstance();(也可以这么写)
Single ss =Single.s;
}
}
步骤:
1、私有化该类构造函数。
2、通过new在本类中创建一个本类对象。
3、定义一个公有的方法,将创建的对象返回。
附上代码:
/饿汉式
class Single//类一加载,对象就已经存在了。
{
private static Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
//懒汉式
class Single2//类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象。
//延迟加载形式。
{
private static Single2 s = null;
private Single2(){}
public static Single2 getInstance()
{
if(s==null)
s = new Single2();
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1==s2);
// Single ss = Single.s;
// Test t1 = new Test();
// Test t2 = new Test();
Test t1 = Test.getInstance();
Test t2 = Test.getInstance();
t1.setNum(10);
t2.setNum(20);
System.out.println(t1.getNum());
System.out.println(t2.getNum());
}
}
class Test
{
private int num;
private static Test t = new Test();
private Test(){}
public static Test getInstance()
{
return t;
}
public void setNum(int num)
{
this.num = num;
}
public int getNum()
{
return num;
}
}