分类 JavaSE 下的文章

[scode type="green" size=""]类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。[/scode]

public class Test {
    public static void main(String[] args) {
        //Car car=new Car();
        //Engin engine =car.new Engine()

        //1.几乎用不到
        //2.先new出来外部类new 对象.new 内部类
        Car.Engine engine = new Car().new Engine();
        engine.fire();
    }
}

class Car {
  
    public static String brand="马自达";
    String name="2023新款马自达";
    //内部类
    public class Engine {
        String name="雕牌引擎";
  
        public void fire(){
            String name="马氏点火";
            System.out.println(name);
            System.out.println(this.name);
            //调用外部类的变量方法
            System.out.println(Car.this.name);
        }
    }
}

内部类使用场景

定义在另一个类中的类,它体现了一种代码的隐藏机制和访问控制机制。当往往只有外部类调用此类时,所以就没必要专门设置一个JAVA文件存放这个类。

内部类特点

总结一下内部类访问成员的特点

既可以访问内部类成员、也可以访问外部类成员

如果内部类成员和外部类成员同名,可以使用类名.this.成员区分

静态内部类

使用static修饰内部类
public class Outer{
  public int age=100;
  public static String schoolName="北大";
  //静态内部类
  public static class Inner{
     public void test(){
       //静态内部类不能访问外部实例成员
   
      //静态内部类可以访问外部静态成员
      System.out.println(schoolName);
     }
  }
}

局部内部类

定义在方法里面的类
public class Student{
  public void study(){
   //局部内部类:定义在外部类中的方法中 
   //只能在外部类之中创建对象
   class Mobie{
     public void test(){
       System.out.prinln("局部内部类Mobile,test方法执行了")
    }
   }
  }
}

匿名内部类

匿名内部类是一种特殊的局部内部类;所谓匿名,指的是程序员不需要为这个类声明名字。
public class Test{
    public static void main(String[] args){
        //定义一,定义子类继承父类 实现抽象方法
        Animal a1=new Dog();
        a1.say();
        //方法二 不定义子类 用匿名内部类写法
        Animal a2=new Animal(){
            @Override
            public void say(){
                System.out.println("kkkkk");
            }
        };
        a2.say();
        animalPkSay(new Animal() {
            @Override
            public void say() {
                System.out.println("鹅鹅鹅饿");
            }
        });
    }
  
    public static void animalPkSay(Animal animal){
        animal.say();
    }
}
abstract class Animal{
    String name;
    public abstract void say();
}
class Dog extends Animal{
    @Override
    public void say(){
        System.out.println("汪汪");
    }
}

匿名内部类的使用场景

方法参数是抽象类或者接口时 可以使用匿名内部类简化写法

如果方法实现简单 推荐使用匿名内部类 如果方法实现复杂 推荐定义子类

接口 interface

java提供了一个关键词interface 用这个关键词来定义接口这种特殊结构
public interface 接口名(){
  //成员变量(常量)
  //public static final String NAME="张三"
  //public static final 不加 java自动帮你加上
   String NAME="张三";
  //成员方法(抽象方法)
  //public abstract 不加 java 自动帮你加上
  void test1();
}
接口的常量可以通过接口名.常量名

接口的好处

弥补了类单继承的不足,一个类同时可以实现多个接口。
让程序可以面向接口编程,这样程序员可以灵活方便的切换各种业务实现。

接口使用场景

对象有什么?

比如:

我有车

我有房

我有钱

....

JDK8接口的新特性

随着JDK版本的升级,在JDK8版本以后接口中能够定义的成员也做了一些更新,从JDK8开始,接口中新增的三种方法形式。

我们看一下这三种方法分别有什么特点?

默认方法:必须使用default修饰,默认会被public修饰 实例方法:对象的方法,必须使用实现类的对象来访问。私有方法:必须使用private修饰。(JDK 9开始才支持的) 实例方法:对象的方法。

静态方法:必须使用static修饰,默认会被public修饰

public interface A {
    /**
     * 1、默认方法:必须使用default修饰,默认会被public修饰
     * 实例方法:对象的方法,必须使用实现类的对象来访问。
     */
    default void test1(){
        System.out.println("===默认方法==");
        test2();
    }

    /**
     * 2、私有方法:必须使用private修饰。(JDK 9开始才支持的)
     *   实例方法:对象的方法。
     */
    private void test2(){
        System.out.println("===私有方法==");
    }

    /**
     * 3、静态方法:必须使用static修饰,默认会被public修饰
     */
     static void test3(){
        System.out.println("==静态方法==");
     }

     void test4();
     void test5();
     default void test6(){

     }
}
接下来我们写一个B类,实现A接口。B类作为A接口的实现类,只需要重写抽象方法就可以了,对于默认方法不需要子类重写。

代码如下:

public class B implements A{
    @Override
    public void test4() {

    }

    @Override
    public void test5() {

    }
}
最后,写一个测试类,观察接口中的三种方法,是如何调用的
public class Test {
    public static void main(String[] args) {
        // 目标:掌握接口新增的三种方法形式
        B b = new B();
        b.test1();    //默认方法使用对象调用
        // b.test2();    //A接口中的私有方法,B类调用不了
        A.test3();    //静态方法,使用接口名调用
    }
}
综上所述:JDK8对接口新增的特性,有利于对程序进行扩展。

接口的其他细节

一个接口可以继承多个接口
public class Test {
    public static void main(String[] args) {
        // 目标:理解接口的多继承。
    }
}

interface A{
    void test1();
}
interface B{
    void test2();
}
interface C{}

//比如:D接口继承C、B、A
interface D extends C, B, A{

}

//E类在实现D接口时,必须重写D接口、以及其父类中的所有抽象方法。
class E implements D{
    @Override
    public void test1() {

    }

    @Override
    public void test2() {

    }
}
接口除了上面的多继承特点之外,在多实现、继承和实现并存时,有可能出现方法名冲突的问题,需要了解怎么解决(仅仅只是了解一下,实际上工作中几乎不会出现这种情况)
1.一个接口继承多个接口,如果多个接口中存在方法声明冲突,则此时不支持多继承
2.一个类实现多个接口,如果多个接口中存在方法声明冲突,则此时不支持多实现
3.一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会有限使用父类的方法
4.一个类实现类多个接口,多个接口中有同名的默认方法,则这个类必须重写该方法。
综上所述:一个接口可以继承多个接口,接口同时也可以被类实现。

abstract 抽象

Java关键字abstract,它是抽象的意思,可以修饰类也可以修饰方法

被abstract修饰的类,就是抽象类

被abstract修饰的方法,就是抽象方法(不允许有方法体)

抽象类不能被创建出来也就是不能被new出来

抽象方法只能在抽象类中创建

案例

/**
 * @author TongHui
 * @date 2021.04.05 14:23
 */
public abstract class Animal {
    private String name;
    private int age;


    //动物能叫?
    //抽象方法不是先方法
    //抽象方法只能在抽象类中定义
    //抽象的好处抽象类中有些方法不适合实现
    public abstract void say();

    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;
    }
}

抽象类的注意事项

抽象类也可以定义普通的方法和变量

抽象类的优点

提高代码的复用性

什么时候用抽象类

当类与类之间是包含关系 比如说:狗是动物 我是人 面包是食物

final常量修饰符

可以修饰类、修饰方法、修饰变量

修饰类: 该类称为最终类 特点不能被继承

修饰方法: 该方法成为最终方法 特点不能被重写

修饰变量: 该变量只能被赋值一次

常量

常量: 定义一个常量
为了方便在其他类中被访问所以一般还会加上public修饰符

被static final两个修饰符修饰
常量命名规范:建议都采用大写字母命名,多个单词之前有_隔开

                            //常量名 
public static final String SCHOOL_NAME = "常量值";

final变量注意事项

如果变量是对象,只是对象地址只能赋值一次
final  int[] a={1,2,3,4};
//可以被修改
a[0]=100;
System.out.println(a[0]);

final使用场景

final一般应用于保存配置信息

final 优点

复用性高

多态

多态实在继承实现情况下的一种现象 表现为多态 行为多态

多态写法: 父类引入指向子类对象(对象多态)

相同父类方法 具体子类不同 执行的内容不同(行为多态)

多态好处

提高代码复用性

解耦合

深耦合和浅耦合

深耦合: 类与类的关联关系太紧密

浅耦合: 类与类的关联关系比较小

权限修饰符

什么是权限修饰符?

权限修饰符是用来限制类的成员(成员变量 成员方法 构造器...)能够被访问的范围

每一种权限修饰符能够被访问的范围如下

修饰符在本类中在同一个包下的其他类任意包下的子类任意包下的任意类里
私有方法private
缺省缺省
受保护的protected
公开的public
private < 缺省 < protected < public

super

访问父类成员

super.成员变量 //访问父类成员变量

super.成员方法 //调用父类成员方法

super() //调用父类的无参构造器

super(参数)//调用父类的有参构造器

this

访问本类成员

this.成员变量 //访问本类成员变量

this.成员方法 //访问本类的成员方法

this() //调用本类的空参构造器

this(参数) //调用本类的有参构造器

super与this注意事项

注意:this和super访问构造方法 只能用到构造器的第一句话否则会报错

包含父类属性的有参构造器

当子类继承父类且父类存在非私有属性, 子类的构造方法可以接收父类的属性

super的使用场景

当子类被创建出来时,想同时调用父类构造器时用super();

继承extends

子类可以继承父类的非私有成员(成员变量和成员方法)

继承后对象的创建是由子类和父类共同实现的

继承好处

提高代码复用性

继承的注意事项

Java 只支持单继承,无法多继承

但是可以多层继承

java的祖宗类Object 如果不显示的继承object java是默认继承的

static静态修饰符

static 静态
static修饰成员变量(静态成员变量)和成员方法(静态成员方法 )
成员变量一共分为静态(类)变量和实例变量
静态变量是要使用static修饰符 进行 修饰
由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量
实例变量无法通过类名.变量名获取 
实例变量是属于对象的,需要通过对象才能调用:对象.实例变量

静态使用场景

静态经常用在工具类

生成验证码

/**
 * 生成验证码的工具类
 * @author TongHui
 * @date 2023.04.14 10:59
 */
public class CaptchaUtil {
    public static String getCaptcha(int length) {
        // 1、定义2个变量 一个是记住最终产生的随机验证码 一个是记住可能用到的全部字符
        String code = "";
        String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        Random r = new Random();
        // 2、开始定义一个循环产生每位随机字符
        for (int i = 0; i < length; i++) {
            // 3、随机一个字符范围内的索引。
            int index = r.nextInt(data.length());
            // 4、根据索引去全部字符中提取该字符
            code += data.charAt(index); // code = code + 字符
        }
        return code;
    }
}
//使用方法 CaptchaUtil.getCaptcha(验证码长度)

static注意事项

  • 类方法中可以直接访问类的成员,不可以直接访问实例成员
  • 实例方法中既可以直接访问类成员,也可以直接访问实例成员
  • 实例方法可以出现this关键词,类方法中不可以使用this关键词

静态代码块

//静态代码块
//对象被加载的时候执行 静态代码块只会被执行一次
//无法访问实例方法和成员变量
static{

}

实例代码块

//实例代码块可以访问的实例成员

{
  可以直接访问实例成员
}

public class Test{
    public static void main(String[] args){
        String s1 = null;
        String s2 = "Hello Wolrd";
  
        //这里会出现NullPointerException异常,调用者不能为null
        System.out.println(s1.equals(s2));
        //此时不会有NullPointerException异常,底层会自动先判断空
        System.out.println(Objects.equals(s1,s2));
  
        //判断对象是否为null,等价于==
        System.out.println(Objects.isNull(s1)); //true
        System.out.println(s1==null); //true
  
        //判断对象是否不为null,等价于!=
        System.out.println(Objects.nonNull(s2)); //true
        System.out.println(s2!=null); //true
    }


}
Objects是一个工具类,提供了一些方法可以对任意对象进行操作。主要方法如下
方法名说明
public static boolen equals(Object a,Object b)先做非空判断 再比较两个对象
public static boolean isNull(Object obj)判断对象是否为null 为null返回true 反之
public static boolean nonNull(Object obj)判断对象是否不为null 不为null返回true 反之