子父类中的构造函数的特点:
子类的构造函数中第一行有一个默认是的隐试语句,super();
子类的实例化过程中,子类所有的构造函数都会默认访问父类中的空参构造函数。
为什么会这样呢?
那是因为子类继承了父类,获取到了父类中的属性,所以在使用父类内容前,要先看看父类是如何对自己的内容进行初始化的。 所以子类在构造对象的时候必须访问父类的构造函数。所以子类的构造函数中的第一句默认隐士的调用了super()语句。如果父类中没有定义空参构造函数,那么子类的构造函数必须用super明确调用父类中哪个构造函数。
一个对象实例化的过程:Person p = new Person();
1,JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有的情况下)。
2,在堆内存(heap)中开辟空间,分配地址。
3,并在对象空间中,对 对象中的属性进行默认初始化。
4,调用对应的构造函数进行初始化
5,在构造函数中,第一行会先到调用父类中构造函数进行初始化
6,父类初始化完成后,在对子类的属性进行显示初始化
8,初始化完成后,将这片空间的地址赋值给引用变量。
构造函数:也就是创建对象时调用的函数,
作用:给对象进行初始化 创建对象都必须通过构造函数初始化。
一个类如果没有定义构造函数,那么该类中会有一个默认的空参构造函数,如果在类中定义了指定的构造函数那么就会使用指定的构造函数。
构造函数和一般函数的区别是什么?
当对象创建时,就会调用与之对应的构造函数,对对象进行初始化 但是一般函数当对象创建后需要使用它的时候才调用。
单例设计模式:就是可以保证一个类在内存中的对象是唯一的。
如何保证对象的唯一性?
* 不允许其他程序创建该类对象。(私有化构造函数)
* 通过new在本类中创建一个对象。
* 定义一个公有方法,将创建的对象返回。
1、饿汉式
步骤:
1. 私有化构造函数
2. 声明这个类的引用类型变量 private static Single s;Single就是一个类的实例。
3. 声明公共静态方法获取本类的对象
代码:
class Single
{
private static Single s = new Single(); //声明这个类的引用类型变量
private Single(){} // 私有化构造函数
public static Single getInstance() //声明公共静态方法获取本类的对象
{
return s;
}
}
懒汉式
- 私有化构造函数
- 声明这个类的静态的引用并将它置为null;
- 编写对外的静态方法获取实例
当类一旦加载,这时是没有对象的,只用使用者调用了getInstance()方法, 才会创建对象
class Single
{
private Single(){}
private static Single s = null;
public static Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
懒汉试单例设计模式会引起线程安全问题,当两个或多个对象同时进入s==null 判断时。会创建多个新对象,那么如何解决呢?
- 加锁,
synchronized()
{
if(s==null){
s=new Single();
}
return s;
}
但这样加锁效率很低,可以这样进行改善
if(s==null){
synchronized()
{
if(s==null){
s=new Single();
}
return s;
}
}
匿名对象:
没有名字的对象。
new Car();//匿名对象,
其实就是定义对象的简写格式。
当对象对方法仅进行一次调用的时候,就可以简写成匿名对象
new Car().num = 5; //这是一个对象,他的编号是5
new Car().color = "green";//这是另一个对象,他的编号不知道,但是他颜色是green
new Car().run();//这个对象什么属性都不知道,但是它调用了run()方法
静态方法只能访问静态成员;静态方法中不能使用this或者super关键字。 main函数就是静态的,他储存在方法区。
这个主函数有什么特殊之处吗?
- 首先这玩意的格式是固定的
- 它可以被JVM所识别和调用
- 访问权限是最大的public
- static 不需要对象就可以直接用主函数名调用即可
- void 主函数是没有具体的返回值的
- String[] args代表主函数的参数列表是一个字符串数组类型的参数,每个元素都是一个字符串。
静态到底什么时候用?
- 静态变量
当分析对象中所具备的成员变量都是相同的那个,这时的这个成员变量就可以被static所修饰。也就是这个属性对象中都有,所以他属于类自身的,可以用static修饰。
- 静态函数
函数什么时候用static修饰就参考一点,看这个函数的功能是否有访问到对象中的特有成员,简单地说从源代码看,如果这个函数需要访问非静态的成员变量那么他就是非静态的函数或者方法,如果不需要那么就可以定义为静态的。
- 构造代码块:它可以给所有对象初始化
class A
{
static{静态代码块}
{
//构造代码块
}
public A(){
//构造函数
}
}
构造函数是给对应的对象做初始化的,具有针对性。
静态代码块,它随着类的加载而执行,格式为static{},且只执行一次,因为类只加载一次啊!
局部代码块限定着局部变量的生存周期。
继承
继承的好处:提高了代码的复用性。并且让类与类之间产生了联系,给第三特征多态提供了前提。 继承的弊端:打破了封装性。
Java中支持单继承。不直接支持多继承。Java支持多重继承。(\C继承B,B继承A)
单继承:一个子类只有一个直接父类,
多继承:一个子类可以有多个父类(java·中不允许,进行了改良)
不直接支持的原因:因为多个父类中有相同的成员,会产生调用不确定性。
在java中是通过“多实现”的方式来体现。
当使用一个继承体系时,我们应该
-
查看该类中的顶层类,了解该类体系的基本功能。
-
创建体系中的最子类对象,完成功能的使用。
当本类的成员和局部变量同名时用this区分;
当子父类中的成员变量同名时用super区分父类;
This:代表一个本类对象的引用。
Super:代表一个父类空间。
当子父类中出现成员函数一模一样的情况,会运行子类的函数。这种现象称为覆盖操作也就是说子类重写了父类的方法。
重载。同一个类中。Overload
覆盖。子类中。也称重写。Override
覆盖注意事项:
- 子类的方法覆盖父类的方法时,子类权限必须大于父类的权限。
- 静态只能覆盖静态的,或被静态覆盖 什么时候才用覆盖? 当对一个类的子类进行扩展时子类需要保留父类的功能声明,但要定义该功能的特有内容时,就可以覆盖父类的方法。
final关键字
1. final是一个修饰符,它可以修饰类,修饰方法,修饰变量
2. final修饰的类不可被继承
3. final修饰的方法不能被覆盖(重写)
4. final修饰的变量是一个常量,只能赋值一次
为什么要使用final?
因为在程序中如果一个数据是固定不变的那么可以直接使用,但是这样不假思索的使用在我们的代码中阅读性较差,所以不如直接用final给他固定,例如π;
代码规范请参照阿里巴巴开发手册。
常量所有字母都大写,多个单词用 _ 隔开,类名通常用名词代替,方法名开头第一个字母是小写,之后的单词要大写,变量小写。
静态代码块,构造代码块,构造函数的 执行顺序
1. 先执行父类的静态内容,父类静态内容执行完成后,接着去执行子类的静态内容
2. 当子类的静态内容执行完毕后,再去看父类有没有非静态代码块如果有,就执行父类的非静态代码块,接着执行父类的构造函数;
3. 父类的构造函数执行完成后,会去查看子类有没有非静态代码块,如果有就执行子类的非静态代码块,执行完毕后再执行子类的构造函数
综上:先执行父类的静态代码块-->子类的静态代码块-->父类的非静态代码块-->父类的构造函数-->子类的非静态代码块-->子类的构造函数;
抽象类的特点:
抽象类具有构造方法,作用是给子类对象初始化。
抽象类用abstract关键字修饰,他不能和static,private,final共存。
抽象类与一般类的区别:
1. 相同点:抽象类和一般类都是用来描述事物的,都定义了成员
2. 不同点:一般类有足够的信息描述事物,但抽象类可能信息不足;一般类中不可定义抽象方法,但抽象类可以,同时抽象类也可以定义非抽象方法。一般类可以实例化,但抽象类不可以。抽象类一定是一个父类,由子类覆盖他的成员函数。
接口(interface)
定义:当一个抽象类的所有方法都是抽象方法的时候,这时候可以将抽象类定义成接口。
格式 interface 接口名{}
对于接口中常见的成员:这些成员都有固定的修饰符:
- 全局常量:public static final;
- 抽象方法:public abstract
- 因此我们可以说接口中的成员都是公共权限
类和类之间的联系可以是继承,类和接口之间的关系是实现。
特点
-
接口不能实例化,只能由一个实现接口的子类覆盖整个接口中的所有抽象方法后,这个子类才可以实例化,否则这个子类家就是一个抽象类。
-
一个类在继承一个类的同时,还可以实现多个接口,因此接口的出现避免了单继承的局限性
-
接口与接口之间是继承关系而且可以多继承 interface1 extend interface2,interface3....
接口和抽象类的异同点
相同点:都是不断向上抽取得来的
不同点:
-
抽象类需要被继承,接口需要被实现,继承的话只能是单继承,但实现的话可以是多实现
-
抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。但是接口中的方法都是抽象的,需要被子类去实现
-
抽象类的继承是所属关系,在定义体系的共性内容,接口的实现是补充关系,在定义体系额外的功能。