static关键字
介绍
static表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量。
其中,被static修饰的成员变量,叫做静态变量;被static修饰的成员方法,叫做静态方法。
静态变量
调用方式:类名调用(推荐)、对象调用
特点:
● 被该类所有对象共享
● 不属于对象,属于类
● 随着类的加载而加载,优先于对象存在
//所有对象的teacherName将会被赋值为“阿伟”
Student.teacherName = "阿伟";
Student s1 = new Student();
s1.setName("小李");
s1.setAge(18);
System.out.println(s1.toString());//Student{name = 小李, age = 18, teacherName = 阿伟}
Student s2 = new Student();
System.out.println(s2.toString());//Student{name = null, age = 0, teacherName = 阿伟}
内存图
注意:
静态区里边的变量是对象共享的,在内存当中只有一份,“谁要用谁去拿”;而非静态的变量是每一个对象独有的。
静态方法
调用方式:类名调用(推荐)、对象调用
特点:
● 多用在测试类和工具类中
● Javabean类中很少会用
拓展:工具类、测试类、Javabean类的区别
● Javabean类:用来描述一类事物的类。比如,Student,Teacher,Dog等
● 测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口
● 工具类:不是用来描述一类事物的,而是帮我们做一些事情的类
书写工具类,需注意:
● 类名见名只意(如StudentUtil)
● 私有化构造方法(不让外界创建它的对象)
● 方法定义为静态(方便调用)
练习
定义一个工具类求学生年龄最大值
工具类:
public class StudentUtil {
//私有化构造方法
private StudentUtil(){}
public static int getMaxAge(List<Student> list){
if(list.size() == 0)return -1;
int max = list.get(0).getAge();
for(int i = 1;i < list.size(); i++){
int maxTemp = list.get(i).getAge();
if(maxTemp > max){
max = maxTemp;
}
}
return max;
}
}
测试类:
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
Student stu1 = new Student("张三",15,"男");
Student stu2 = new Student("李四",16,"男");
Student stu3 = new Student("王五",13,"女");
list.add(stu1);
list.add(stu2);
list.add(stu3);
//用工具类当中的方法获取集合中最大学生的年龄
int maxAge = StudentUtil.getMaxAge(list);
System.out.println(maxAge);//16
}
static的注意事项
● 静态方法只能访问静态变量和静态方法(静态方法只能访问静态)
● 非静态方法可以访问静态变量或静态方法,也可以访问非静态的成员变量和非静态的成员方法(非静态可以访问所以)
● 静态方法中是没有this关键字
public class Student {
String name;
int age;
static String teacherName;
public void show1(){
System.out.println(name + ", " + age + ", " + teacherName);
//非静态方法调用静态方法和非静态方法(this可省略不写)
//this:表示当前方法调用者的地址值
//这个this:是由虚拟机赋值的
this.method();
this.show2();
}
public void show2(){
System.out.println("成功调用此方法");
}
public static void method(){
System.out.println("静态方法");
//不能用this调用静态方法(只能直接调用),也不能调用非静态方法
method1();
}
public static void method1(){
//只能输出静态成员变量,非静态不行
System.out.println(teacherName);
}
}
继承
继承的概述
java中提供了一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系
public class Student extends person{}
其中,Student称为子类(派生类),Person称为父类(基类或超类)
使用继承的好处
● 可以把多个子类中重复的代码抽取到父类中了,提高代码的复用性。
● 子类可以在父类的基础上,增加其他的功能,使子类更加强大。
什么时候用继承?
当类与类之间,存在相同(共性)的内容,并满足子类是父类的一种,就可以考虑使用继承,来优化代码
继承的特点
● Java只支持单继承,不支持多继承(一个儿子只能有一个父亲,不能有多个)、但支持多层继承
多层继承:子类A继承父类B,父类B可以继承父类C(B是A的直接父类,C是A的间接父类)
● Java中所有的类都直接或者间接继承于Object类。
练习
所作图:
代码如下:
六个Javabean类:
public class Animal {
public void eat(){
System.out.println("吃饭");
}
public void drink(){
System.out.println("喝水");
}
}
public class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Dog extends Animal{
public void lookHome(){
System.out.println("狗在看家");
}
}
public class Ragdoll extends Cat{
}
public class LiHua extends Cat{
}
public class Husky extends Dog{
public void breakHome(){
System.out.println("哈士奇正在拆家!!");
}
}
public class Teddy extends Dog{
public void touch(){
System.out.println("泰迪正在蹭我的腿~");
}
}
测试类:
public class Text {
public static void main(String[] args) {
//1.创建布偶猫对象
Ragdoll r = new Ragdoll();
r.eat();//吃饭
r.drink();//喝水
r.catchMouse();//猫抓老鼠
//2.创建哈士奇对象
Husky h = new Husky();
h.eat();//吃饭
h.drink();//喝水
h.lookHome();//狗在看家
h.breakHome();//哈士奇正在拆家!!
}
}
继承的注意事项
子类到底能继承父类中的哪些内容
即构造方法不能被继承,成员变量都能被继承,成员方法只继承虚方法表中的方法
对于成员变量:
● 私有的确实可以继承,但得用set/get方法进行赋值和访问
● 静态成员变量可以直接赋值和访问
public class Fu {
public String name;
public static int age;//静态成员变量
private String gender;//私有变量
public void setGender(String gender){
this.gender = gender;
}
public String getGender(){return this.gender;}
}
public class Zi extends Fu{
public int score;
}
测试类:
public class Text {
public static void main(String[] args) {
Zi z = new Zi();
z.name = "张三";
z.score = 100;
z.age = 15;//age为父类静态成员变量
z.setGender("男");
System.out.println(z.name + ", " + z.score + ", " + z.age + ", " + z.getGender());//张三, 100, 15, 男
}
}
对于成员方法:
从最顶级的父类开始设立了一个虚方法表,一代一代传给自己的子类,大大提高程序的性能
如果子类对象调用的方法不在虚方法表中,则会在上代中一代一代去找
内存图演示:
继承中成员变量、方法和构造方法的访问特点
对于成员变量:
● 就近原则:谁离我近,我就用谁(先在局部位置找,本类成员位置找,父类成员位置找,逐级往上)
● 出现重名需要用this、super关键字来指定访问
public class Fu {
String name = "Fu";
}
public class Zi extends Fu{
String name = "Zi";
public void ziShow(){
String name = "ziShow";
System.out.println(name);//ziShow
System.out.println(this.name);//Zi
System.out.println(super.name);//Fu
}
}
public class Text {
public static void main(String[] args) {
Zi zi = new Zi();
zi.ziShow();
/*
ziShow
Zi
Fu*/
}
}
对于成员方法:
● 直接调用满足就近原则:谁离我近,我就用谁
● super调用,直接访问父类
public class Fu {
public void eat(){
System.out.println("吃米饭");
}
public void drink(){
System.out.println("喝水");
}
}
public class Zi extends Fu{
public void lunch(){
//先在本类中查看eat和drink方法,就会调用子类的,如果没有,就会调用父类中继承下来的eat和drink方法
eat();
drink();
//直接调用父类的eat和drink方法
super.eat();
super.drink();
}
@Override
public void eat(){
System.out.println("吃意大利面");
}
@Override
public void drink(){
System.out.println("喝奶茶");
}
}
public class Text {
public static void main(String[] args) {
Zi zi = new Zi();
zi.lunch();
/*
吃意大利面
喝奶茶
吃米饭
喝水*/
}
}
补充说明:方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法重写
书写格式
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法
@Override重写注解
其是放在重写后的方法上,校验子类重写时语法是否正确
方法重写的本质
即子类覆盖了从父类中继承下来的虚方法表里面的方法
方法重写注意事项和要求
● 重写方法的名称、形参列表必须与父类中的一致
● 子类重写父类方法时,访问权限子类必须大于等于父类(空着不写<protected<public)
● 子类重写父类方法时,返回值类型子类必须小于等于父类
● 只有被添加到虚方法表中的方法才能被重写
● 重写方法尽量和父类保持一致
练习
所作图:
代码如下:
public class Dog {
public void eat(){
System.out.println("狗在吃狗粮");
}
public void drink(){
System.out.println("狗在喝水");
}
public void lookHome(){
System.out.println("狗在看家");
}
}
public class Husky extends Dog{
public void breakHome(){
System.out.println("狗在拆家");
}
}
public class SharPei extends Dog{
@Override
public void eat(){
super.eat();
System.out.println("吃骨头");
}
}
public class ChineseDog extends Dog{
@Override
public void eat(){
System.out.println("狗在吃剩饭");
}
}
public class Text {
public static void main(String[] args) {
Husky h = new Husky();
h.eat();
h.drink();
h.lookHome();
h.breakHome();
ChineseDog cd = new ChineseDog();
cd.eat();
cd.drink();
cd.lookHome();
}
/*
* 狗在吃狗粮
狗在喝水
狗在看家
狗在拆家
狗在吃剩饭
狗在喝水
狗在看家*/
}
总结
对于构造方法:
● 子类构造方法的第一行,有一个默认的super();
● 默认先访问父类中无参的构造方法,再执行自己。
● 子类不能继承父类的构造方法,但是可以通过super调用
● 如果想要方法文父类有参构造,必须手动书写。
this、super使用总结
● this:理解为一个变量,表示当前方法调用者的地址值;
● super:代表父类存储空间。
测试
带有继承结构的标准Javabean类
答案:
父类:
public class Employee {
private String id;
private String name;
private double salary;
//ptg生成javabean
public Employee() {
}
public Employee(String id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Employee{id = " + id + ", name = " + name + ", salary = " + salary + "}";
}
public void work(){
System.out.println("正在工作");
}
public void eat(){
System.out.println("吃米饭");
}
}
两个子类:
public class Manage extends Employee{
private double bouns;
//alt+insert重造构造器
public Manage() {
}
public Manage(String id, String name, double salary, double bouns) {
//调用了父类的有参构造器
super(id, name, salary);
this.bouns = bouns;
}
//ptg
public double getBouns() {
return bouns;
}
public void setBouns(double bouns) {
this.bouns = bouns;
}
public String toString() {
return "Manage{bouns = " + bouns + "}";
}
//方法的重写
@Override
public void work() {
System.out.println("经理正在管理其他人");
}
}
public class Cooker extends Employee{
//alt+insert
public Cooker() {
}
public Cooker(String id, String name, double salary) {
super(id, name, salary);
}
@Override
public void work() {
System.out.println("厨师正在炒菜");
}
}
测试类:
public class Text {
public static void main(String[] args) {
Manage m = new Manage("001","zhangsan", 7843.5, 213.5);
System.out.println(m.toString());
m.eat();
m.work();
Cooker c = new Cooker();
c.setId("002");
c.setName("lisi");
c.setSalary(6743);
System.out.println(c.toString());
c.eat();
c.work();
}
// Manage{bouns = 213.5}
// 吃米饭
// 经理正在管理其他人
// Employee{id = 002, name = lisi, salary = 6743.0}
// 吃米饭
// 厨师正在炒菜
}
标签:Java,String,void,System,---,进阶篇,println,public,out
From: https://blog.csdn.net/2301_76909842/article/details/141161665