static

被static修饰的成员变量,叫做静态变量
特点:
被刻类所有对象共享
不属于对象,属于类
随着类的加载而加载,优先与对象存在

调用方式:
1.类名调用:类名.变量
2.对象名调用

shift+alt+上下键: 可以上下移动这行的文字

javabean类:用来描述一类事物的类。比如student。teacher.
测试类:用来检查其它类是否书写正确,带有main方法的类,是程序的入口
工具类:不是描述一类事物的类。而是帮我们做一类事情的类。

工具类:
用static修饰方法 这样可以不用创建对象 直接用类名曲调用
工具类中一般都把构造方法私有化 这样可以防止创建工具类的对象 因为创建工具类没有什么意义

写一个工具类

import java.util.StringJoiner;

public class arrayUilt {

    private arrayUilt(){}

    public static String printArr(int[] arr){
        StringJoiner ret = new StringJoiner(",","[","]");
        for (int i = 0; i < arr.length; i++) {
            ret.add(arr[i]+"");
        }
        return ret.toString();
     }

     public static Double average(double[] arr){
        double ave = 0.0;

         for (int i = 0; i < arr.length; i++) {
             ave += arr[i];
         }
        return ave/arr.length;
     }

}

static注意事项

static是java中的一个修饰符,可以修饰成员变量,成员方法
static修饰的是静态
静态方法只能访问静态方法和静态变量
非静态方法可以访问所有成员方法和成员变量
静态方法中没有this关键字,非静态有默认的this关键字
静态方法可以看做是共享的,它和对象无关,是随着类的加载而加载,可以通过类名进行调用
类的class字节码文件加载时,静态变量就加载到堆中的静态区,所以静态的不能调用非静态的
静态方法直接可以相互调用
在这里插入图片描述

重新认识主函数main

public static void main(String[] args){ }

public : 由jvm虚拟机调用,扩大访问权限 可以让虚拟机在外面找到并访问它 不管是否在同一个包中都能调用
static: 由jvm虚拟机调用,不用创建对象,直接类名调用
因为main方法是静态的,所以测试类中的方法也是静态的
void: 被jvm调用,不需要给jvm返回值
main:方法名 程序的主入口 一个通用的名称,虽然不是关键字,但是被jvm识别 其它名称不能识别
String[] args : 以前用于接收键盘录入数据的,现在没有用了 默认是空 什么也没有

继承

什么时候用继承

当类与类之间存在相同的内容时,并满足子类是父类中的一种,就可以考利使用继承,来优化代码

2.继承的格式

public class 子类 extends 父类 {};

继承特点?

子类可以得到父类的属性和行为,子类可以使用
子类可以在父类的基础上新增其它功能。
java只能单继承:一个类只能继承一个直接的父类
java支持多层继承
java中所有的类都直接或者间接继承object类
jvm会检测类是否有父类,如果没有就直接继承object
子类中只能访问父类中非私有的成员

子类到底能继承父类中哪些内容

构造方法:
不管是非私有还是私有的都不能继承 (构造方法的名称需要时类名)
成员变量:
1.非私有:能直接继承

2.私有的:能继承 但是不能直接用 只能通过成员方法去访问他,比如说getName()
成员方法:
在虚方法表中的能直接继承
不在虚方法表中的不能继承
(虚方法表:非private,非final,非static修饰的成员方法
子类会在直接父类的基础上添加自己的的虚方法)

继承中:成员变量的访问特点

是采用就近原则:
先在局部位置找,再到本类成员变量中找,再到父类中找,一层一层寻找,如果没有找到就会报错
访问局部位置的成员变量直接写变量名就行:name
访问本类中:this.name
访问父类中的: super.name
如果先访问间接父类的就要使用类型转换:(间接父类类名)this.name

继承中 成员方法的访问特点

方法重写的本质:子类重写的方法覆盖了虚方法表中的方法
1.子类方法的访问权限必须大于父类的访问权限
2.子类在返回值类型必须小于父类的
3.子类在重写父类的方法时,返回值,访问权限尽量与父类保持一致
4.只有能添加到虚方法表中的方法才能被重写
5.子类重写方法时,方法名必须与父类保持一致

@Override注释可以检查方法重写是否正确,并且可读性良好

小练习:
在这里插入图片描述

public class dog{

     public void eat(){
         System.out.println("吃狗粮");
     }

     public void drink(){
      System.out.println("喝水");
     }

     public void lookhome(){
         System.out.println("看家");
     }

}




public class dog1 extends dog {
    @Override
    public void eat(){
     
    }

    public void attackhome(){
        System.out.println("拆家");
    }

}


public class dog2 extends dog{

    @Override
    public void eat(){
        super.eat();
        System.out.println("吃骨头");
    }

}



public class dog3 extends dog{

    @Override
    public void eat(){
        System.out.println("吃剩饭");
    }

}

继承中 构造方法的访问特点

子类不能继承父类的构造方法,但是可以通过super调用
系统会默认的在子类的构造方法 调用super() 不管写不写都会执行 如果自己手动写需要把super写在第一行
在子类的构造方法中虚拟机会默认先访问父类的无参构造
如果想调用父类的有参构造需要自己手动写

this,super使用总结

this:相当于一个局部变量 储存当前调用者的地址值
super: 代表父类储存空间
在这里插入图片描述
this(…) 这可以访问本类其它的构造方法 如果在this中传入参数就相当于给那些变量给个默认值

多态

面对对象三大特征:封装 继承 多态
封装:对象代表什么 就得封装对应的数据 ,并提供对应数据的行为

认识多态

什么是多态:
对象的多种形态
多态的前提:
有继承或者实现关系
有父类引用指向子类对象
有方法的重写
多态的好处:使用多态可以接受所有的子类对象

多态中调用成员的特点

调用成员变量:编译看左边 运行也看左边
编译的时候会在父类中找看是否存在这个成员变量 如果不存在就直接报错 如果存在 就直接调用父类的成员变量
调用成员方法:编译看左边 运行看右边
编译的时候会在父类中找看时候存在这个成员方法 如果不存在直接报错 如果存在 就去子类的方法表中调用这个方法 所以如果子类重写了这个方法 就会直接用重写之后的方法了
成员变量不支持多态,成员方法支持多态

多态的优势和弊端

多态的优势:方法中,使用父类作为参数 可以接受所有子类对象
多态的弊端:不能使用子类的特有功能
引用数据类型的数据转换,有几种:
自动类型装换,强制类型装换
强制类型转化能解决什么问题:
可以转化为真正的子类,从而调用子类特有的功能
在转化过程中,可能会转换错误,要先用instanceof判断一下

先判断a是否为子类类型 如果是就直接转化为子类 并命名为b
如果不是放回false
if(a instanceof 子类 b){
   b.子类方法();
}

多态的小练习

在这里插入图片描述

package duotai_practice;

public class person {

    private String name;
    private int age;

    public person() {
    }

    public person(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;
    }

//    public void keepPet(dog d,String somethid){
//
//    }
//
//    public void keepPet(cat c,String somethind){
//
//    }

    public void keepPet(animal a,String somethind){

//        System.out.printf("年龄为%d岁的老王养了一只%s颜色的%d岁的狗\n",this.age,a.getColor(),a.getAge());
//        a.eat(somethind);
         if(a instanceof dog d){
             System.out.printf("年龄为%d岁的老王养了一只%s颜色的%d岁的狗\n",this.age,d.getColor(),d.getAge());
             d.eat(somethind);
         }else if(a instanceof cat c){
             System.out.printf("年龄为%d岁的老李养了一只%s颜色的%d岁的猫\n",this.age,c.getColor(),c.getAge());
             c.eat(somethind);
         }
    }

}

package duotai_practice;

public class animal {
    private int age;
    private String color;

    public animal() {

    }
    public animal(int age, String color) {
        this.age = age;
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void eat(String something){
        System.out.println("动物在吃" + something);
    }

}

package duotai_practice;

public class dog extends animal{
    public dog() {
    }

    public dog(int age, String color) {
        super(age, color);
    }


    @Override
    public void eat(String somethind){
        System.out.printf("%d岁的%S颜色的狗两只前腿死死的抱住%s猛吃\n",this.getAge(),this.getColor(),somethind);
    }



    public void lookhome(){
        System.out.println("看家");
    }



}

package duotai_practice;

public class cat extends animal{

     public cat(){

     }

     public cat(int age,String color){
         super(age,color);
     }

     @Override
     public void eat(String somethind){

         System.out.printf("%d岁的%s颜色的猫咪这者眼睛侧着头吃%s\n",this.getAge(),this.getColor(),somethind);
     }

     public void catchMouse(){
         System.out.println("逮老鼠");
     }

}

测试类

package duotai_practice;

public class Test {

    public static void main(String[] args) {
        cat c = new cat(3,"白");
        dog d = new dog(2,"黑");
        person p1 = new person("老王",30);
        person p2 = new person("老李",25);
        p1.keepPet(d,"骨头");
        p2.keepPet(c,"鱼");
    }

}

包 final 权限修饰符 代码块

什么是包:
包就是文件夹,用来管理不同功能的java类
包名书写规范:
公司名反写+包作用 全部用小写,见名知意
什么叫全类名:
包名+类名
什么时候需要导包 什么时候不需要导包
在同一个包中不需要导包(会先在本包中寻找)
在java.lang中的类不需要导包
其它情况都要导包
当有两个包中相同名的类时,需要用全类名

final

final修饰类:是最终类不能被重写
final修饰方法:不能被修改
final修饰成员变量:变成常量 只能被赋值一次 之后就不能被修改了
常量的注意事项:
修饰基本数据类型:对应的值不能被改变
修饰引用数据类型:对应的地址值不能被改变 内部的属性值可以被改变

权限修饰符

在这里插入图片描述
注:无关系类就是没有继承关系的类
在实际开发应用中一般用private和public
成员变量使用private
成员方法用public
特殊情况:如果类中有方法是抽取其它方法中的共性,一般会私有

代码块

局部代码块:
提前结束变量的生命周期
构造代码块:
抽取所有构造方法中的重复代码
静态代码块:
属于静态的 随着类的加载而加载 只会被调用一次
一般在对一些数据初始化的时候使用

抽象类

抽象类的作用:
抽取共性时,无法确定方法体,就把方法体定义为抽象的
强制子类重写抽象方法
有抽象方法的是抽象类,抽象类不一样有抽象方法
抽象类和抽象方法的格式:
public abstract class 类名{ }
public abstract 返回类型 方法名(参数列表);

接口

接口的定义

public interface 接口名{}
接口与类时实现关系 用implement来表示
public class 类名 implement 接口名{ }
接口不能实例化

接口的子类(实现):
子类必须重写所有的抽象方法
或者子类自己本身是抽象类

注:子类可以同时实现多个接口 继承父类的同时也能实现多个接口接口
public class 类名 extends 父类 implement 接口1,接口2,接口3,…{}

接口中成员的特点:

成员变量:默认用public static final修饰 为常量
构造方法:接口中没有构造方法
成员方法:默认为public abstract 为抽象方法
jdk7以前只能定义抽象方法

接口与类之间的关系

类与类:继承关系 可以单继承 不能多继承 但是可以多层继承
接口与类:实现关系 一个类可以实现多个接口 但是需要重写所有的抽象方法
接口与接口:继承关系 可以单继承也可以多继承 如果实现类实现的是最小面的接口 那么需要重写所有的抽象方法

接口中的默认方法(jdk8之后添加的)

默认方法的作用:解决接口升级问题
就是如果接口中需要添加新的方法 为了避免让所有实现这个接口的类都要重写这个方法
在需要重写的时候再重写就行

默认方法要用default修饰
格式为: public default 返回类型 方法名(){}
,默认方法重写的时候要把default关键字去掉
如果有实现类实现了多个接口中有相同名字的默认方法 那么这个默认方法必须重写 如果不重写 在创建对象 调用这个默认方法时 会不知道是要调用哪一个

接口中的静态方法(jdk8之后添加的)

静态方法是不能被实现类重写的 因为静态方法不能被继承
调用的时候不能使用实现类名或者对象名去调用 只能使用接口名去调用 如果实现类中有相同方法名 用实现类名去调用 调用的是实现类中的方法
格式:public static 返回类型 方法名() { }

接口中的静态方法(jdk9之后添加的)

接口中的静态方法只为接口服务
格式:
private 返回类型 方法名(){};
为静态的方法服务的
private static 放回类型 方法名(){};

抽取一下共性 但是这个方法又不想被外界访问

public interface inter1 {
    
    public static void start(){
        System.out.println("开始");
        log();
    }
    
    public static void end(){
        System.out.println("结束");
        log();
    }
    
    private static void log(){
        System.out.println("记录日志的100行代码");
    }

}

接口的应用

接口是规则,是行为的抽象 想要哪个类拥有这种行为 就实现这个接口就行
当一个方法的参数是一个接口时,可以传入所有实习的类 这就称为接口的多态 也遵守编译看左边 运行看右边

适配器设计模式

1.当一个接口中抽象方法过多时,但是又只需要用一部分的时候,就可以用适配器模式
2.书写步骤:
编写中间类XXXadopt,并空实现接口中的抽象方法
让真正的实现类去继承这个中间类,并重写需要用的方法
为了避免创建其它类创建适配器对象,一帮用abstract修饰适配器

内部类

初识内部类

类的五大成员:属性,方法,构造方法,代码块,内部类
什么是内部类:写在一个类中的类
什么时候用到内部类:属于外部类的一部分,但是单独存在没有意义
内部类中能使用外部类中的成员 包括私有的
外部类使用内部类中的成员时 需要创建对象

成员内部类:

内部类的成员方法的定义:
内部类可以用private,空着,protected,public 修饰 访问权限和外部类中的成员一样
在jdk16之前不能定义静态变量

获取内部类的两种方法:
1.在外部类中设置返回内部类对象的方法 接收时可以用内部类的父类 如果实在找不到就用共同点的父类object
2.外部类.内部类 名称 = new 外部类().new 内部类();
当内部类和外部类成员重名的时候可以用 外部类.this.成员 来调用外部类成员 this.成员 调用内部类中的成员 this关键字记录的是类实例之后的地址
Outer.this 是编译器自动给内部类中添加的

静态内部类:

静态内部类也属于成员内部类的一种
静态内部类只能访问外部类的静态成员
要访问非静态的需要创建外部类对象

获取静态内部类中的方法:
非静态方法: 先创建静态内部类,再调用方法 Outer.Inner in = new Outer.Inner();
调用静态方法:外部类.内部类.方法名;

局部内部类:

static public protect private只能修饰成员变量 不能修饰局部变量

局部内部类: 定义在方法中的类
可以访问方法中的变量和外部类的中成员
外界无法使用,必须在方法内部创建对象使用

匿名内部类:

1.什么是匿名内部类:隐藏了名字的内部类,可以写在局部位置,也可以写在成员位置。
2.匿名内部类的格式:

new 类名或者接口名(){};
匿名内部类的主体是{}中的内容
类名或者接口名代表继承这个类或者实现这个接口
()代表的是空参构造
new 代表的是创建一个对象
;代表结束

3.格式的细节:
1.继承或者实现 方法重写 创建对象
整体就是一个类的子类对象或者接口的实现类对象
使用场景:
当参数是接口或者类时,
以接口为例,可以传递这个接口的实现类对象,如果实现类只要使用一次,就可以使用匿名内部类简化代码。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐