一、static静态
static关键字:静态的意思,可以修饰成员变量、成员方法。
1.1 static修饰成员变量
成员变量按照有无static修饰,分为两种: 1、类变量:有static修饰,属于类,随着类的加载而加载,在计算机中只有一份,会被类的所有对象共享 方式1: 类名.类变量(推荐) eg: Student.name = "张三"; 方式2: 对象名.类变量(不推荐) eg: Student s1 = new Student(); s1.name = "李四"; 2、实例变量:无static修饰,属于每个对象自己,,每个对象中都有一份 对象名.实例变量 eg:s1.age = 18; 总结 类变量既可以使用类名调用,也可以使用对象名调用,推荐类名方式 实例变量只能使用对象名调用
1、什么场景下需要定义类变量
某个数据只需要一份,且希望能够被多个对象共享
2、访问自己类中的类变量,是否可以省略类名不写?
可以的
注意:在某个类中访问其他类里的类变量,必须带类名访问
1.2 static修饰成员方法
成员方法的分类: 1、类方法 有static修饰的方法, 属于类,可以直接用类名访问,也可以用对象访问 调用方式: 类名.方法名() [推荐] 对象名.方法名() [不推荐] 2、实例方法 无static修饰的方法, 属于对象,只能用对象访问 调用方式: 对象名.方法名()
public class Demo1 {
public static void main(String[] args) {
//需求1: 类方法调用
Student.print1();
//需求2: 实例方法调用
Student s1 = new Student();
s1.print2();
s1.print1();
}
}
class Student {
//编写一个类方法(使用Static修饰方法)打印hello
public static void print1(){
System.out.println("hello");
}
//编写一个实例方法(不使用Static修饰方法)打印HelloWorld
public void print2(){
System.out.println("HelloWorld");
}
}
1、类方法有啥应用场景?
可以用来设计工具类
2、工具类是什么
工具类就是一些完整功能、经常使用的方法所在的类
3、为什么工具类要用类方法,而不是用实例方法?
类方法可以不创建对象,直接调用,使用方便,节省内存
实例方法需要创建对象来调用,会浪费内存
4、工具类定义时有什么建议?
工具类不需要创建对象, 建议将工具类的构造器私有化。
1.3注意事项
-
类方法中可以直接访问类的成员,不可以直接访问实例成员。(static方法访问static的成员(变量和方法),不能访问非static的成员)
-
实例方法中既可以直接访问类成员,也可以直接访问实例成员。(非static访问一切)
-
实例方法中可以出现this关键字,类方法中不可以出现this关键字的。(static不能用this)
本质: this指的是对象 静态的内容是跟随类加载而加载的, 此时还没有对象, 也就没有this和实例内容
1.4 (了解)代码块
代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。 代码块分为两种: 静态代码块: 格式:static { } 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。 作用:完成类的初始化,例如:对类变量的初始化赋值。 实例代码块: 格式:{ } 特点:每次创建对象时,执行实例代码块,并在构造器前执行。 作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。
public class Demo {
public static void main(String[] args) {
//类加载
System.out.println(Student.name);//1.加载Student 2.查找name属性并返回
System.out.println(Student.name);
System.out.println(Student.name);
//对象创建
Student student = new Student();
Student student2 = new Student();
}
}
class Student {
//静态变量
public static String name;
//实例变量
public int age;
//静态代码块:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次, 可以用来对类变量进行初始化赋值
static {
System.out.println("执行static代码块");
name = "莉莉";
}
//实例代码块:每次创建对象时,执行实例代码块,并在构造器前执行。
{
System.out.println("执行实例代码块");
age = 18;
}
}
static { }只执行一次,{ }每次创建对象都会执行。运行结果:
二、继承
2.1 概述
Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。 class B extends A{ B类: 子类(派生类) A类: 父类(基类或者超类) } 继承的特点 子类能继承父类的所有成员变量和方法,但不能直接访问父类的非私有成员变量和方法 子类内部可以使用父类的非私有成员变量和方法 继承体系下类对象的创建 子类的对象是由子类、父类共同完成的
public class Demo {
public static void main(String[] args) {
//继承下对象的创建: 子类的对象是由子类和父类共同完成的
B b = new B();
System.out.println(b.i);
//System.out.println(b.j);//父类私有, 子类是无法直接使用的
//System.out.println(b.k);//子类私有, 无法直接方法(封装的特点)
b.print1();
//b.print2();//父类私有, 子类是无法直接使用的
b.print3();
}
}
/*
父类
*/
class A {
//公有成员变量和方法
public int i;
public void print1(){
System.out.println("父类中的print1方法");
}
//私有成员变量和方法
private int j;
private void print2(){
System.out.println("父类中的print2方法");
}
}
//使用extends关键字表明继承了A类
class B extends A{
private int k;
public void print3(){
//父类的非私有的成员变量和方法,子类可以直接使用
System.out.println(i);
print1();
//父类私有的成员变量和方法,子类可以继承到, 但是无法使用
//System.out.println(b);
//print2();
}
}
继承的好处: 减少了重复代码的编写,提高代码的复用性(将多个类中的重复代码向上抽取到父类中)
1.3 权限修饰符
用来限制类中的成员(成员变量、成员方法、构造器、代码块…)能够被访问的范围。 种类和作用 private: 本类 缺省: 本类、本包类 protected: 本类、本包类、子孙类 public: 任意类
1.4 单继承
Java中继承的特点 Java只支持单继承,不支持多继承,但是支持多层继承 为什么Java不支持多继承 如果一个Java类继承了多个父类, 而多个父类中右恰好有一样的方法, 代码会产生冲突 Object类 Object类是Java中所有类的祖宗类,我们写的任何一个类,都是Object的子类或子孙类 也就是说:java中所有的类都直接或间接的继承Object类(只要我们的类不明确使用extends继承类,那么它就默认继承Object)
1.5 方法重写
方法重写 当子类觉得从父类中继承到的某个方法不好用,或者无法满足自己的需求时 子类可以重写一个方法名称、参数列表一样的方法,去覆盖掉继承到的这个方法,这就是方法重写 注意:重写后,方法的访问会遵循就近原则 注意事项: 1. 在重写的方法上标注Override注解,可以指定java编译器,检查我们方法重写的格式是否正确 2. 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限( public > protected > 缺省 ) 3. 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。 4. 私有方法、静态方法不能被重写,如果重写会报错的。 应用场景 重写toString来展示对象中的属性
public class Demo {
public static void main(String[] args) {
Son son = new Son();
son.makeFriend();//结果:正在通过添加微信的方式交朋友~~~
}
}
class Father{
//交朋友
public Father makeFriend(){
System.out.println("正在通过写信的方式交朋友~~~");
return null;
}
}
class Son extends Father{
//交朋友
@Override
public Son makeFriend(){
System.out.println("正在通过添加微信的方式交朋友~~~");
return null;
}
}
1.6 子类构造器特点
1.6.1 子类访问成员特点
父子类下访问成员的顺序 1、在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。 子类局部-->子类成员-->父类成员 2、两个关键字 强行访问子类的成员: this 强行访问父类的成员: super
public class Demo {
public static void main(String[] args) {
Son son = new Son();
son.show();
}
}
class Father {
//父类成员
int num = 10;
}
class Son extends Father {
//子类成员
int num = 20;
public void show() {
//子类局部
int num = 30;
System.out.println(num);//30 就近原则
System.out.println(this.num);//20 子类成员访问
System.out.println(super.num);//10 父类成员访问
}
}
1.6.2 子类构造器
子类构造器的特点 子类的全部构造器,都会先调用父类的构造器,再执行自己。 子类构造器是如何实现调用父类构造器的: 默认情况下,子类全部构造器的第一行代码都是 super() (写不写都有) ,它会调用父类的无参数构造器。 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(...),指定去调用父类的有参数构造器。
public class Demo {
public static void main(String[] args) {
Son son = new Son();
}
}
class Father{
private String name;
private int age;
private String address;
public Father() {
System.out.println("调用Father无参数构造器");
}
class Son extends Father{
private String school;
public Son() {
System.out.println("调用Son无参数构造器");
}
}
public class Demo {
public static void main(String[] args) {
Son son = new Son();
}
}
class Father{
private String name;
private int age;
private String address;
public Father(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
System.out.println("调用Father有参数构造器");
}
}
class Son extends Father{
private String school;
public Son() {
super("张三",20,"石家庄");
System.out.println("调用Son无参数构造器");
}
}
1.7 子类构造器应用
子类构造器调用父类构造器的应用场景 我们经常在子类构造器中调用父类的有参构造器给父类传递参数来完成父类对象的初始化
public class Demo {
public static void main(String[] args) {
//需求: 使用Teacher的带参数构造创建对象,并对三个属性赋值
Teacher teacher = new Teacher("李四",18,"C语言");
System.out.println(teacher);
}
}
class People {
private String name;
private int age;
public People() {
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Teacher extends People {
private String skill;
public Teacher() {
}
public Teacher(String name, int age, String skill){
super(name,age);
this.skill = skill;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + getName() + '\'' +
", age=" + getAge() +
", skill='" + skill + '\'' +
'}';
}
}
1.8 this调用兄弟构造器
this() 任意类的构造器中,是可以通过this(…) 去调用该类的其他构造器的。 注意事项 this(…) 、super(…) 都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,反之亦然。
public class Demo {
public static void main(String[] args) {
//需求: 通过够全参构造创建对象并完成初始化
Student student1 = new Student("张三", 18, "黑马程序员");
System.out.println(student1);
//需求: 如果用户没有指定学校, ,默认学校为"黑马程序员顺义校区"
Student student2 = new Student("李四", 19);
System.out.println(student2);
}
}
class Student {
private String name;
private int age;
private String school;
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
public Student(String name, int age) {
this(name, age, "黑马程序员顺义校区");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school='" + school + '\'' +
'}';
}
}