文章目录
面向对象编程(高级版本)
1、类变量
1.1、引出
有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?
public static void main(String[] args) {
//定义一个变量count, 统计有多少小孩加入了游戏
int count = 0;
Child child1 = new Child("白骨精");
child1.join();
//count++;
child1.count++;
Child child2 = new Child("狐狸精");
child2.join();
//count++;
child2.count++;
Child child3 = new Child("老鼠精");
child3.join();
//count++;
child3.count++;
//===========
//类变量,可以通过类名来访问,输出的值都是3
System.out.println("共有" + Child1.count + " 小孩加入了游戏...");
System.out.println("child1.count=" + child1.count);//3
System.out.println("child2.count=" + child2.count);//3
System.out.println("child3.count=" + child3.count);//3
}
class Child {
//类
private String name;
//定义一个变量count ,是一个类变量(静态变量) static 静态
//该变量最大的特点就是会被Child 类的**所有的对象实例共享**
public static int count = 0;
public Child(String name) {
this.name = name;
}
public void join() {
System.out.println(name + " 加入了游戏..");
}
}
不管static变量存在哪里,共识:
1、static变量是同一个类所有对象共享 ;
2、static类变量,在类加载的时候就生成了。
1.2、入门类变量
1.3、使用注意细节
//普通属性/普通成员变量/非静态属性/非静态成员变量/实例变量 都是不加static的叫法
private int num = 10;
2、类方法
重点:静态方法只能访问静态成员;普通成员都可以访问
3、main方法
- 在main()方法中,我们可以直接调用main 方法所在类的静态方法或静态属性。
- 但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
public class Main01 {
//静态的变量/属性
private static String name = "小曾哥";
//非静态的变量/属性
private int n1 = 10000;
//静态方法
public static void hi() {
System.out.println("Main01 的hi 方法");
}
//非静态方法
public void cry() {
System.out.println("Main01 的cry 方法");
}
public static void main(String[] args) {
//可以直接使用name
//1. 静态方法main 可以访问本类的静态成员
System.out.println("name=" + name);
hi();
//2. 静态方法main 不可以访问本类的非静态成员
//System.out.println("n1=" + n1);//错误
//cry();
//3. 静态方法main 要访问本类的非静态成员,需要先创建对象, 再调用即可
Main01 main01 = new Main01();
System.out.println(main01.n1);//ok
main01.cry();
}
}
4、代码块
//静态属性的初始化
private static int n1 = getN1();
public static int getN1() {
System.out.println("getN1 被调用...");
return 100;
}
// 普通属性初始化
private int n2 = getN2();//普通属性的初始化
public int getN2() {
//普通方法/非静态方法
System.out.println("getN2 被调用...");
return 200;
}
完整代码
public class CodeBlockDetail02 {
public static void main(String[] args) {
A a = new A();// (1) A 静态代码块(2) getN1 被调用...(3)A 普通代码(4)getN2 被调用...(5)A() 构造器被调用
}
}
class A {
{
//普通代码块
System.out.println("A 普通代码块01");
}
private int n2 = getN2();//普通属性的初始化
static {
//静态代码块
System.out.println("A 静态代码块01");
}
//静态属性的初始化
private static int n1 = getN1();
public static int getN1() {
System.out.println("getN1 被调用...");
return 100;
}
public int getN2() {
//普通方法/非静态方法
System.out.println("getN2 被调用...");
return 200;
}
//无参构造器
public A() {
System.out.println("A() 构造器被调用");
}
}

分析:new Test() —>调用static sample sam = new Sample() -->Sample类–>输出 静态成员sam初始化—>static -->输出static块执行 -->sam1成员初始化 -->test默认构造函数被调用
5、单例设计模式
饿汉式和懒汉式
6、final关键字

补充:fianl可以修饰类、属性、方法和局部变量
fianl 修饰类,这个类就不能继承了
final修饰属性,就是一个常量值
final修饰方法,那么这个方法就是最终方法,不能被重写,但是可以继承使用。
final修饰局部变量,最终就会变成局部常量,不能修改的。
7、抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类。
7.1、快速入门
一般来说,抽象类会被继承,有其子类来实现抽象方法。
7.2、 具体细节
7.3、抽象类的模板设计模式
具体步骤:将不确定性的方法用抽象类进行抽象化,然后在子类中实现这个方法,可以提高代码的复用性。
7.4 普通类 vs 抽象类
抽象类不能被实例化;
抽象类可以有抽象方法,只需申明,无须实现;
有抽象方法的类一定是抽象类;
抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
抽象方法不能声明为静态、不能被static、final修饰。
8、接口
在JDK8版本后,接口类中方法可以包括[1、抽象方法 2、默认方法 default 3、静态方法 static]
8.1、 接口应用场景
8.2、接口细节
8.3、接口 VS 继承
继承 : 当子类继承了父类,就自动的拥有父类的功能
如果子类需要扩展功能,可以通过实现接口的方式扩展.
可以理解实现接口是对java单继承机制的一种补充.
8.4、接口 VS 抽象类
相同点:
1、都不能被实例化。
2、接口的实现类和抽象类的子类只有全部实现了接口或者抽象类中的方法后才可以被实例化。
不同点:
1、接口使用interface修饰;抽象类使用abstract修饰;
2、接口只能定义抽象方法不能实现方法,抽象类既可以定义抽象方法,也可以实现方法。
3、单继承,多实现。接口可以实现多个,只能继承一个抽象类。
4、接口强调的是功能,抽象类强调的是所属关系
8.5、接口的多态
9、内部类
如果定义类在局部位置(方法中/代码块) :(1) 局部内部类(2) 匿名内部类
定义在成员位置(1) 成员内部类(2) 静态内部类
public class InnerClass01 {
//外部其他类
public static void main(String[] args) {
}
}
class Outer {
//外部类
private int n1 = 100;//属性
public Outer(int n1) {
//构造器
this.n1 = n1;
}
public void m1() {
//方法
System.out.println("m1()");
}
{
//代码块
System.out.println("代码块...");
}
class Inner {
//内部类, 在Outer 类的内部
}
9.1、局部内部类
class Outer02 {
//外部类
private int n1 = 100;
private void m2() {
System.out.println("Outer02 m2()");
}//私有方法
public void m1() {
//方法
//1.局部内部类是定义在外部类的局部位置,通常在方法
//3.不能添加访问修饰符,但是可以使用final 修饰
//4.作用域: 仅仅在定义它的方法或代码块中
// 加了final修饰符,不能继承
final class Inner02 {
//局部内部类(本质仍然是一个类)
//2.可以直接访问外部类的所有成员,包含私有的
private int n1 = 800;
public void f1() {
//5. 局部内部类可以直接访问外部类的成员,比如下面外部类n1 和m2()
//7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,使用外部类名.this.成员)去访问
// 老韩解读Outer02.this 本质就是外部类的对象, 即哪个对象调用了m1,Outer02.this 就是哪个对象
System.out.println("n1=" + n1 + " 外部类的n1=" + Outer02.this.n1);
System.out.println("Outer02.this hashcode=" + Outer02.this);
m2();
}
}
//6. 外部类在方法中,可以创建Inner02 对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
9.2、匿名内部类
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
基于接口
class Outer04 {
//外部类
private int n1 = 10;//属性
public void method() {
//方法
//基于接口的匿名内部类
//老韩解读
//1.需求: 想使用IA 接口,并创建对象
//2.传统方式,是写一个类,实现该接口,并创建对象
//3.老韩需求是Tiger/Dog 类只是使用一次,后面再不使用
//4. 可以使用匿名内部类来简化开发
//5. tiger 的编译类型? IA
//6. tiger 的运行类型? 就是匿名内部类Outer04$1
/*
我们看底层会分配类名Outer04$1
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
}
//7. jdk 底层在创建匿名内部类Outer04$1,立即马上就创建了Outer04$1 实例,并且把地址返回给tiger
//8. 匿名内部类使用一次,就不能再使用
*/
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
};
System.out.println("tiger 的运行类型=" + tiger.getClass());
tiger.cry();
// 传统方法
//class Tiger implements IA {
//
// @Override
// public void cry() {
// System.out.println("老虎叫唤...");
// }
// }
//class Dog implements IA{
// @Override
// public void cry() {
// System.out.println("小狗汪汪...");
// }
// }
class Outer04 {
//外部类
private int n1 = 10;//属性
public void method() {
//
//基于类的匿名内部类
//1. father 编译类型Father
//2. father 运行类型Outer04$2
//3. 底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test 方法");
}
}
*/
//4. 同时也直接返回了匿名内部类Outer04$2 的对象
//5. 注意("jack") 参数列表会传递给构造器
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了test 方法");
}
};
System.out.println("father 对象的运行类型=" + father.getClass());//Outer04$2
father.test();
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头...");
}
};
animal.eat();
class Father {
//类
public Father(String name) {
//构造器
System.out.println("接收到name=" + name);
}
public void test() {
//方法
}
}
abstract class Animal {
//抽象类
abstract void eat();
}
9.3、成员内部类
9.4、静态内部类