目录
static
有无static修饰的成员变量
有无static修饰的成员方法
static的注意事项
代码块
静态代码块
实例代码块
单例设计模式
饿汉式单例写法
懒汉式单例写法
继承
基本概念
注意事项
权限修饰符
单继承
object
方法重写
子类方法中访问其他成员(成员变量,成员方法)
子类构造器
static
静态,可以修饰成员变量,成员方法
有无static修饰的成员变量
成员变量按照有无static修饰,分为两种:
(1)类变量: 有static修饰,属于类,在计算机里只有一份,会被类全部对象共享(每个对象都会有,只需要设置一次)
(2)实例变量(对象的变量):无static修饰,属于每个对象的(需要对每一个变量进行设置)
像上面这个图一样,static修饰的name变量是s1和s2共享的,age变量需要对s1和s2分别设置
推荐用类名访问类变量: 类名.类变量
下面是我们访问到类中的变量的流程图: 我们的类创建到方法区中,我们的类变量会被存放到堆内存中,我们new出来的对象也会放到堆内存中,我们栈内存会存放一些指令,当我们要访问age时直接到堆内存中访问修改,想访问name时会跳到方法区找到类,然后通过类访问到类变量
访问自己的类变量是可以省略不写类名的
有无static修饰的成员方法
类方法:静态方法,属于类,可以直接用类名访问,也可以用对对象访问
实例方法: 对象的方法
啥叫工具类: 工具类中的方法都是类方法, 每一个类方法都是用来完成一个功能,不需要创建对象
static修饰的成员方法一般应用在工具类中,而不是实例方法中
当我们想要调用一个类的方法的时候,仅仅只是调用方法,我们直接将这个方法指定成类方法,到时候我们想要调用这个方法的时候直接,用 类名.成员方法 就行了,就不用创建对象,在调用对象的实例的方法,如果再创建一个对象,对象会占内存,这样会浪费内存
工具类定义的时候有什么要求? 工具类不需要创建对象,建议将工具类的构造器私有化
static的注意事项
1.类方法中可以直接访问类的成员,不可以直接访问实例成员
2.实例方法既可以直接访问类成员,也可以直接访问实例成员
3.实例方法中可以出现this关键字,类方法不可以出现this关键字的
因为我们调用实例方法的时候,是用对象名.实例方法的,其实是有一个对象,this就是我们这个对象
而我们一般调用类方法的时候,一般是用类名.类方法.没有对象,那我这个this就没有指向的对象了
代码块
静态代码块
格式: static { }
特点: 类加载的时候自动执行,由于类只会加载一次,所以静态代码块也只会执行一次
作用:完成类的初始化,一般可以对类变量进行初始化赋值
但是代码块只会执行一次,只是在一开始的时候加载类的时候去执行,我们在下面进行验证
实例代码块
格式 : { }
特点: 每次创建对象时,执行实例代码块,并在执行构造器前执行
单例设计模式
饿汉式单例写法
调用类方法的时候,对象已经创建了的
public class Student {
// 1.必须私有类的构造器
private Student()
{
}
// 2.定义一个类变量记住类的一个对象
private static Student a = new Student();
//3.定义一个类方法返回类的对象
public static Student getObject()
{
return a;
}
创建唯一的一个对象
懒汉式单例写法
第一次调用方法就创建这个对象,以后调用的时候都返回这个对象
import org.w3c.dom.ls.LSOutput;
public class Student {
// 1.把类的构造器私有
private Student()
{
}
// 2. 定义一个类变量,用于储存这个类的一个对象
private static Student s1;
// 3. 定义一个类方法,这个方法要保证第一个调用时
// 才创建一个对象,后面调用的时候都会返回一个对象
public static Student getObject()
{
if(s1 == null)
{
s1 = new Student();
}
return s1;
}
}
public class test {
public static void main(String[] args) {
Student stu1 = Student.getObject();
Student stu2 = Student.getObject();
System.out.println(stu1 == stu2);
}
}
我们发现打印出来的结果是true,说明这个设计模式仅仅创建了一个对象
继承
基本概念
Java中提供了一个关键字extends,这个关键字,可以让一个类和另一个类建立起父子关系
继承的特点: 子类能继承父类的非私有成员(成员变量,成员方法)
继承后对象的创建: 子类的对象是由子类,父类共同完成的
我们可以用继承来简化代码,不让代码那么繁琐
假若说我要写两个对象,第一个是老师,老师的数据有名字,具有的技能
第二个是快递员,快递员的数据有名字,送快递的单数
我们要创建两个对象的话一般会按照下面这样来创建
// 快递员对象
public class Courier {
private String name;
private int number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
// 老师对象
public class Teacher {
private String name;
private String skill;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
我们会发现:老师和快递员都会有一个相同的成员属性:名字
我们可以整一个父类,父类People对象中有neme方法,让老师对象和快递员对象都继承得到父类的公共属性和方法
// 快递员的对象
public class Courier extends People {
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
// 老师对象
public class Teacher extends People{
private String skill;
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
当我们创建老师对象的时候也会访问到父类中的共有方法,通过共有方法,我们就可以设置老师的姓名
public class test {
public static void main(String[] args) {
Teacher t1 = new Teacher();
t1.setName("李小谦");
System.out.println(t1.getName());
t1.setSkill("爱讲物理课");
System.out.println(t1.getSkill());
}
}
注意事项
权限修饰符
public private protected 缺省
权限的大小关系: public > protected > 省略 > private
下面是他们的访问范围
单继承
Java是单继承的,一个类只能继承一个直接父类,Java中的类不支持多继承,但是支持多层继承的
但是支持多继承
class A{}
class B extends A{}
class C extends B {}
object
object类是Java中所有的类的祖宗
我们在设计类的时候,会默认指定object类的子类
方法重写
啥是方法重写?
当子类觉得父类中的某个方法不好用,或者满足不了自己的需求时,子类可以重写一个方法名称,参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写
注意:重写后,方法的访问Java会遵循就近原则
我们先来展示一下什么是方法重写
当我们创建一个C对象的时候,调用print1和print2实例方法的时候,会打印重写方法里面的内容
尽量在上面标注一个@Override,表示我们在改写父类中的方法
子类方法中访问其他成员(成员变量,成员方法)
按照就近原则
子类构造器
特点: 子类的全部构造器,都会先调用父类的构造器,再执行自己
子类构造器是如何实现调用父类构造器的?
默认情况下,子类全部构造器的第一行代码都是super()(写不写默认都是有的),他会调用父类的无参数构造器,如果父类没有无参数构造器,则我们必须在子类构造器中的第一行手写super(里面带有参数,和父类中有参数构造器中的参数一一对应)
我们来看看执行结果
假如说我将父类构造器改为有参数构造器,变成下面这样
那我们也必须在子类中手写一个带参数super(),才能执行子类构造器的代码
我们看看问什么这么做呢?