static关键字
在静态方法中不能使用成员变量,只能使用静态属性;
对属性
名称 | 静态属性(类属性) | 成员变量(对象属性) |
---|---|---|
定义 | 被static 关键字修饰的属性 | 不被static 关键字修饰的属性 |
定义语法 | static 数据类型 属性名 | 数据类型 属性名 |
访问语法 | 类名.类属性名; | 对象名.属性名; |
存储位置(内存中) | 数据共享区 | 堆中根据对象创建的空间中 |
生命周期 | 类名.class文件被加载到jvm中时产生 jvm消失时,类属性伴随一起消失 | 当对象被创建时产生 当对象所在方法执行完毕后被回收 |
//静态属性定义语法
static 数据类型 属性名;
//静态属性访问语法
类名.静态属性名;//推荐
对象名.静态属性名;//不推荐
注意:
①静态属性被所有对象共享。
②static
关键字只能修饰成员变量,不能修饰局部变量。
对方法
被static
修饰的方法被称为类方法,也叫静态方法。
不被static
关键字修饰的方法称为对象方法,这种方法能够被根据同一个类创建出的每一个对象使用。
//静态方法定义语法
// 或为void 可有可无
public static 返回值类型 方法名(数据类型 参数名,...){
方法体;
//当返回值类型为void时,无return语句
return 数据;
}
//类方法调用语法
类名.静态方法名;//推荐
对象名.静态方法名;//不推荐
注意:
①在静态方法中无论是通过类访问还是通过对象访问都不能直接访问成员变量。
②成员方法及成员变量只能通过创建出的对象来调用。
③静态方法和静态属性既可以通过类来调用也可以通过创建出的对象来调用。
单例模式
设计模式:有经验的前人通过实践总结下来被大家公认的代码设计思想。
单例模式:只能产生一个对象。
懒汉模式
步骤:
①将默认的构造器私有化
②在类中定义一个当前类的类型的静态属性,并且创建当前类的对象。
③提供一个静态方法来返回当前类的静态属性的对象。
class Singleton{
//这种定义方法类似private static int age = 0;
//相当于创建一个类型为Singleton,名为singleton的属性,并赋值为new Singleton();
//在单例类内中创建一个自己本身的对象
private static Singleton singleton = new Singleton();
//将构造私有化
private Singleton() {
}
//获得单例的对象
//这里只有为静态方法时,主函数中才能使用“类名.静态方法名”进行调用
public static Singleton getSingleton() {
return singleton;
}
}
public class TestSingleton {
public static void main(String[] args) {
//获得到的单例的对象赋给s
Singleton s = Singleton.getSingleton();
}
}
饿汉模式
步骤:
①将默认的构造器私有化
②在类中定义一个当前类的类型的静态属性,并且创建当前类的对象。
③提供一个静态方法来返回当前类的静态属性的对象,并且内部使用if语句判断静态属性是否为空,来进行对创建出的自己本身的对象进行赋值。
class Singleton{
//这种定义方法类似private static int age;
//相当于创建一个类型为Singleton,名为singleton的属性,并且初始值为null;
//在单例类内中创建一个自己本身的对象
private static Singleton singleton;
//将构造私有化
private Singleton() {
}
//获得单例的对象
//这里只有为静态方法时,主函数中才能使用类名.静态方法名进行调用
public static Singleton getSingleton() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
public class TestSingleton {
public static void main(String[] args) {
//获得到的单例的对象赋给s
Singleton s = Singleton.getSingleton();
}
}
类的继承(使用extends关键字)
定义:在描述事物的时候,我们如果发现有几个类有重复的成员变量和成员方法,我们就可以使用继承的方式来设计。
特点:子类会把父类所有的成员变量和成员方法继承下来(暂不考虑final关键字)。
class 子类名 extends 父类名{
子类属性;
子类方法;
}
class Father{
String name;
public void introduce() {
System.out.println(name + "正在输出");
}
}
//Son类中没有定义成员变量和成员方法,直接继承Father类的成员变量和成员方法
class Son extends Father{
}
public class Test{
public static void main(String[] args) {
//父类正常创建对象,给成员变量赋值和调用其成员方法
Father father = new Father();
father.name = "Father";
father.introduce();//结果 Father正在输出
Son son = new Son();
//在这里可以正常给Son类继承的成员变量赋值
son.name = "Son";
//在这里可以正常调用Son类继承的成员方法
son.introduce();//结果 Son正在输出
}
}
注意:
①如果父类中包含了某些类中共同的成员变量和成员方法,我们则可以使用继承来设计。
②子类既可以使用extends关键字继承父类的共同成员变量,也可以有自己特有的成员变量和成员方法。
③父类更通用,子类更具体。
④子类只能继承父类中的非private
的成员变量,如果想要继承需要公共的set、get方法。
⑤私有成员方法无法被继承。
⑥java只支持单继承 例:class A extends class B{}
⑦java支持多级继承 例:class A extends class B{}
class C extends class A{}
此时类B对于类C而言是超类。
super关键字
定义:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
用法:
①在子类的成员方法中,访问父类的成员变量。
②在子类的成员方法中,访问父类的成员方法。
③在子类的构造方法中,访问父类的构造方法。
注意:
①在创建子类的对象时,父类的构造先被调用,其次调用子类的构造器。
②子类通过默认构造器创建子类对象时,需要调用父类的默认构造器。(在子类默认构造中隐式调用super();
方法)
③当子类需要使用默认构造器,但父类中存在含参构造器时,只需要在父类中将默认构造器显示地定义出来即可。
④当子类使用含参构造器调用父类含参构造器创建含参对象时,父类中的默认构造器不会被调用。
⑤在子类构造器中调用父类构造器的语法,super();
的调用语句要放在构造器的第一行
1.默认无参构造器super();
2.含参构造器super(参数名,...)
class Father{
String name;
//父类含参构造器
public Father(String name) {
this.name = name;
}
public void introduce() {
System.out.println(name + "正在输出");
}
}
//Son类中没有定义成员变量和成员方法,直接继承Father类的成员变量和成员方法
class Son extends Father{
//子类含参构造器
public Son(String name) {
//super调用父类含参构造器,与this用法相同
super(name);
}
}
public class Test{
public static void main(String[] args) {
//父类正常创建对象,给成员变量赋值和调用其成员方法
Father father = new Father("Father");
father.introduce();//结果 Father正在输出
Son son = new Son("Son");
son.introduce();//结果 Son正在输出
}
}
⑥super
可以表示对父类的引用,我们可以使用super
和this
来区分子类和父类同名的成员变量和成员方法。
⑦在子类继承父类后,访问指定的成员变量/成员方法在内存中的顺序:首先在子类中查找,若子类中没有再去父类中查找。
⑧在子类中可以使用super
语句对父类的成员方法/成员变量进行调用:
1.调用成员变量:super.父类成员变量名;
2.调用成员方法:super.父类成员方法名();
class Father{
String name = "李四";
public void introduce() {
//隐含使用this.name
System.out.println("父类输出自己的成员变量:" + name);
}
public void print() {
System.out.println("父类方法被调用!");
}
}
//Son类中没有定义成员变量和成员方法,直接继承Father类的成员变量和成员方法
class Son extends Father{
String name = "张三";
public void output() {
//隐含使用this.name
System.out.println("子类输出自己的成员变量:"+name);
//当父类和子类有同名的成员变量,但是想要使用父类的成员变量时使用
//"super.父类成员变量名;" 语句进行调用
System.out.println("子类输出调用父类的成员变量:"+super.name);
//隐含使用this.print();
print();
//当父类和子类有同名的成员方法,但是想要使用父类的成员方法时使用
//"super.父类成员方法名();" 语句进行调用
super.print();
}
public void print() {
System.out.println("子类方法被调用!");
}
}
public class Test{
public static void main(String[] args) {
//父类正常创建对象,给成员变量赋值和调用其成员方法
Father father = new Father();
father.introduce();//结果 Father正在输出
Son son = new Son();
son.output();
}
}
输出结果:
父类输出自己的成员变量:李四
子类输出自己的成员变量:张三
子类输出调用父类的成员变量:李四
子类方法被调用!
父类方法被调用!