1. 外部类和内部类

package chapter03;

// 外部类 只能使用 public 或者 默认(default)/什么都不写
public class oop1 {
public static void main(String[] args){

// 内部类的使用
// 1. 先实例化外部类
OuterClass outer = new OuterClass();
// 2. 再实例化内部类
OuterClass.InnerClass innerClass = outer.new InnerClass();
System.out.println(innerClass.name); // 成功输出`内部类`属性
}
}

// 外部类 只能使用 public 或者 默认(default)/什么都不写
class OuterClass{
// 内部类就是在类里面在声明一个类,当成外部类的一个属性使用即可,这样就可以试试用任意的访问权限了
// public private protectd default,也可以使用static来将这个内部类修饰成静态属性
// 内部类的使用需要先将其外部类实例化出来
public class InnerClass{// 这就是一个内部类
String name = "内部类";
}
}

2. 单例模式

package chapter03;

// 外部类 只能使用 public 或者 默认(default)/什么都不写
public class oop1 {
public static void main(String[] args){

// 单例模式的使用(调用对应类的方法生成类)
SingleClass singclass1 = SingleClass.getInstance();
SingleClass singclass2 = SingleClass.getInstance();

// 保证生成的均是同一个对象,地址相同
System.out.println(singclass1 == singclass2); // true,表示两者为同一个对象(地址相同)
}
}

// 单例模式
/*
* 有时候我们不希望某一个类被频繁的实例化生成对象,因为也许这个类里面的属性和方法非常的复杂,这样就会导致
* 内存被疯狂的占用,此时就需要单例模式,所谓单例模式就是给一个类设置其构造函数为 private 模式,这样外部就无法
* 通过new来实例化生成对象,但是我们可以通过 static 关键字来将这个类中某一些方法暴露给外部调用,外部通过
* 调用这些方法来实例化这个类,同时需要在该类实例化是新增判断条件,保证每一次实例化生成的都是同一个类,这就是单例模式
* */
class SingleClass {
// 设置判断条件,判断该类是否以及实例化生成过对象了
private static SingleClass singleclass = null; // 需要设置该变量为 static 这样才能被类的内部的 static方法使用
// 因为 static 方法无法调用成员属性,只能调用static属性,也就是静态属性

// 构造函数设置成private,保证外部无法实例化该类
private SingleClass() {

}

// 对外提供一个静态方法,外部可以通过这个静态方法的调用返回一这个类生成的对象
public static SingleClass getInstance() {
// 做逻辑判断,保证不能重复调用实例化该类生成对象,只返回一个
if ( singleclass == null ) {
singleclass = new SingleClass(); // 在类的内部实例化该类生成都西昂
}
return singleclass;
}
}

3. final关键字

package chapter03;

public class oop1 {
public static void main(String[] args){

}
}

// final 关键字
// Java中提供了一种语法,可以在数据初始化后不被修改,使用关键字final
// final可以修饰变量:变量的值一旦初始化后无法修改
// final可以修饰属性:那么JVM无法自动进行初始化,需要自己进行初始化, 属性值不能发生变化
// 一般将final修饰的变量称之为常量,或者叫不可变变量
// final可以修饰方法,这个方法不能被子类重写
// final可以修饰类,这样类就没有子类了
// final不可以修饰构造方法
// final可以修改方法的参数,一旦修饰,参数就无法修改。

final class Obj{ // 类也可以使用 覅能力关键字来修饰,但是修饰过后无法被子类继承,也就是说没有子类
final String name = "zhangsan"; // 外部实例化后无法修改

public final String username; // 设置一个属性
public Obj(String username) { // 构造函数无法使用final关键字
this.username = name; // 构造函数外部传入参数后无法修改
}

public final void test() { // 方法也是可以使用 final 的,在使用过后,子类继承无法重写

}
}

// 子类继承无法重写父类中被 final 修饰的方法,同样无法继承被 final 修饰的父类
//class Child20 extends Obj {
// public void test() {
//
// }
//}

4. 抽象类和抽象方法

package chapter03;

public class oop1 {
public static void main(String[] args){

}
}

// 抽象 - Abstract(不能和final同时使用) : 抽象类和抽象方法
// 抽象类: 不完整的类就是抽象类(无法直接构建对象,但是可以通过子类间接构建对象) -> abstract class 类名
// 抽象方法: 只用声明而没有实现的方法 -> abstract 返回值类型 方法名(参数)
/*
* 如果一个类中含有抽象方法,那么这个类一定是抽象类,反之则不一定,那么什么是抽象类和抽象方法呢?
* 这个是一个很模糊的概念,我们可以认为抽象类是一种规范,就是将一种很模糊的东西变得清晰,好比中国人是人,
* 美国人也是人,那么人这个概念就是抽象类,但是美国人是白人,中国人是黄种人,我们就可以通过子类(中国人和美国人)
* 去继承这个抽象类(人),慢慢的将这个类变得清晰,由此可见,抽象类只能用于继承. 当一个抽象类中有抽象方法时,
* 子类的继承必须重写该抽象方法,将其补充完整!
* */

// 创建一个抽象类
abstract class Person{
// 编写一个抽象方法
abstract void test();
}

// 子类继承抽象类
class Chinese extends Person{
// 必须重写继承抽象类中的抽象方法
void test(){
System.out.println("中国人...");
}
}