------- android培训、java培训、期待与您交流! ----------
黑马学习日志之六 静态,单例设计模式,继承,多态
1 静态(static)
1.1 静态
作用:用于修饰成员方法和成员变量 不能修饰局部。
特点:随着类的加载而加载,随着类的消失而消失,生命周期最长。
优先于对象存在,被所有对象共享,可以直接被类名调用。
静态方法只能访问静态成员;静态方法不可以写this、super等关键字;
利弊:
利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象都存储一份;
可以直接被类名调用
弊:生命周期过长;访问出现局限性 只能访问静态的成员
1.2 在普通方法和静态方法访问的区别:
普通方法调用:
既可以访问静态成员,也可以访问非静态成员;
可以调用普通变量,还可以调用静态变量;
可以调用普通方法,也可以调用静态方法;
静态方法调用:
只能调用静态变量;
只能调用静态方法;
总结得出:静态只能访问静态。
1.3 静态成员与普通成员的区别:
在内存中的位置
静态成员:方法区中;
普通成员:对内存中;
创建时间与销毁时间
普通成员:随着对象的创建而存在,随着对象的消失而消失;
静态成员:随着类的加载而存在,随着类的消失而消失(生命周期长);
调用上的区别
普通成员:对象.成员;
静态成员:对象.成员 类名.成员;
理解上的区别
静态成员:所有对象共享同一个变量。它是与类相关,类变量;
普通成员:变量是每个对象单独拥有的。它是与对象相关,实例变量、成员变量;
1.4 什么时候用静态?
定义静态成员变量:当对象中出现共享数据时,该数据被static修饰。对象的特有 数据,非静态。
定义静态函数:当功能内部没有访问到非静态数据时,该功能可以定义为静态的。
例子:
class Demo {
int num = 5;
static int num2 = 10;
//普通方法
public void show(){
System.out.println(num);
System.out.println(num2);
}
//静态方法
public static void method(){
System.out.println(num);//错误:无法从静态上下文中引用非静态变量
System.out.println(num2);
show();//错误: 无法从静态上下文中引用非静态 方法 show2()
method();
}
public static void method2(){
System.out.println("嘿嘿");
}
}
class StaticDemo2 {
public static void main(String[] args) {
Demo d = new Demo();
d.show();
d.method();
Demo.method2();
}
}
1.5 静态代码块
格式:static{………}
执行先后顺序:静态代码块 构造代码块 构造函数;
注意:静态代码块只执行一次,在main主函数之前执行;
作用:静态代码块是用来加载数据库驱动的,因为驱动只需要加载一次。
2 设计模式
在编程过程中我们经常会遇到一些典型的问题或需要完成某种特定需求,而这些问题和需求前人也曾经遇到过,他们经过大量理论总结和实践验证之后优选出的代码结构、编程风格、以及解决问题的思考方式,这就是设计模式(Design pattern)。
2.1 单例设计模式
单例设计模式就是要保证在整个程序中某个类只能存在一个对象,这个类不能在创建第二个对象。
单例模式特点:
(1)单例类只能有一个实例。
(2)单例类必须自己自己创建自己的唯一实例。
(3)单例类必须给所有其他对象提供这一实例。
想要保证对象唯一:
(1)为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象
(2)还为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象
(3)为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
这三步用代码体现:
(1)将构造函数私有化
(2)在类中创建一个本类对象
(3)提供一个方法获得该对象
2.2 饿汉式
class Single
{
//1.私有类型构造函数
private Single(){}
//2.创建一个对象
private static Single s = new Single();
//3.创建一个方法,用于得到对象
public static Single getSingle()
{
return s;
}
}
2.3 懒汉式
对象是方法被调用时,才初始化,也叫做对象的延时加载。
class Single
{
private Single s = null;
private single(){}
public static single getSingle() //结合到线程问题,会有弊端。多线程,加锁解决
{
if(s == null)
s = new Single();
return s;
}
}
3 继承
3.1 继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
多个类可以称为子类,单独这个类称为父类或者超类。子类可以直接访问父类中的非私有的属性和行为。通过 extends 关键字让类与类之间产生继承关系。
继承的好处:
继承的出现提高了代码的复用性;
继承的出现让类与类之间产生了关系,提供了多态的前提。
特点:
Java只支持单继承,即一个孩子只有一个父亲
Java支持多层继承。
注意:
不要为了简化代码而继承,必须是类与类之间具有所属关系。看父类中的内容是不是子类中都应该具备的。
3.2 继承中的成员特点
成员变量:
如果方法中找到了,使用方法中的局部变量;
如果在子类中找到了,使用子类中的成员变量
如果在父类中找到了,使用父类中成员变量;
如果在父类中没找到,报错;
如果成员变量与局部变量重名的时候,使用this关键字区分:this.成员变量;
如果子类与父类的成员变量重名的时候,使用super关键字区分 :super.成员变量;
this:本类对象的引用,当前对象的引用;
super:代表父类的内存空间类的标识,父类的引用。
成员方法:
函数的覆盖:子类中出现与父类一模一样的方法时,会出现覆盖操作。
父类中的私有方法不可以被覆盖
在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。super.方法名
注意:
覆盖时,子类方法的覆盖权限一定要大于等于父类方法权限。
静态方法只能覆盖静态。
子类不能覆盖父类私有方法。
构造函数:
子类中所有构造函数默认都会访问父类中的空参数的构造函数;因为每一个构造函数的第一行都有一条默认的语句super();
子类会具备父类中的数据,所以要先明确父类是如何对这些数据初始化的;
当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数;
子类如果不想访问父类的构造方法,可以通过this(参数列表),访问本类的其它构造方法,然后本类的其它构造方法再去访问父类的构造方法;
构造函数的第一行为super(参数列表)或者this(参数列表),二者不能同时存在。
调用本类构造方法: this(参数列表)
调用父类构造方法:super(参数列表)
3.3 final关键字
final表示最终的意思,可以修饰类,方法,变量;
final修饰的方法不可以被覆盖(重写),子类不可以重写父类方法;
final修饰的变量是一个常量,只能赋值一次,不可以进行更改。扩展:如果当前final修饰的变量没有赋值过,可以通过构造函数赋值一次;
final修饰的类不可以被继承。
4 多态
4.1 多态
多态可以理解为事物存在的多种体现形态。
程序中的体现:父类或者接口的引用指向自己子类的对象。
父类 X = new 子类();
多态的前提:
需要存在继承或者实现关系
要有覆盖操作
父类引用指向子类对象
多态好处:提高了程序的扩展性和后期可维护性
多态弊端:只能使用父类的引用访问父类中的成员 父类不能访问子类的特有方法
向上转型:类型提升 Animal a = new Cat();
向下转型:强制转换 Cat c = (Cat)a;
注意:千万不要出现以下操作,就是将父类对象转成子类类型。
Animal a =new Animal();
Cat c =(Cat)a;
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
4.2 多态中的成员特点
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。
例子:
class Fu
{
static int num = 5;
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()
{
System.out.println("fu method_4");
}
}
class Zi extends Fu
{
static int num = 8;
void method1()
{
System.out.println("zi method_1");
}
void method2()
{
System.out.println("zi method_2");
}
void method3()
{
System.out.println("zi method_3");
}
static void method4()
{
System.out.println("zi method_4");
}
}
class DuoTaiDemo4
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num); //成员变量、编译运行都看左边,输出5
f.method3(); // 编译不通过,编译看左边,父类中没有method2()方法
f.method2(); // 运行看右边,输出zi method_2
f.method4(); //静态方法,编译运行都看左边,输出fu method_4 }
}