类变量和类方法
- 类变量
类变量快速入门
类变量,也叫静态变量,所有对象均共享此变量,static修饰 - 不管static变量放在那里,有可能放在堆,也有可能放在方法区,jdk8以上放在堆,之前的版本可能放在静态域方法区
- static变量是同一类所有对象共享
- static类变量在类加载的时候就生成了,所有没有创建对象实例也可以访问
- static类变量除了静态方法,在普通方法可以用this和super修饰
package com.hspedu.static_;
public class VisitStatic {
public static void main(String[] args) {
// 类名.类变量名
System.out.println(A.name);
}
}
class A{
//
public static String name = "韩顺平教育";
}
- static依然准守相应的访问权限
package com.hspedu.static_;
public class ChildGame {
public static void main(String[] args) {
// int count = 0;
Child child1 = new Child("白骨精");
// count++;
child1.count++;
Child child2 = new Child("狐狸精");
// count++;
child2.count++;
//类变量可以通过类名进行访问
System.out.println("共有" + Child.count + "小朋友加入游戏");
System.out.println("共有" + child1.count + "小朋友加入游戏");
System.out.println("共有" + child2.count + "小朋友加入游戏");
}
}
class Child{
private String name;
// 定义一个变量,是一个类变量(静态变量)static 静态
// 该变量最大的特点就是会被所有Child 类的所有对象实例共享
public static int count = 0;
public Child(String name) {
this.name = name;
}
public void join(){
System.out.println(name + "加入游戏");
}
}
-
类变量使用细节
-
类方法
-
类方法是使用场景
package com.hspedu.static_;
public class StaticMethod {
public static void main(String[] args) {
// 创建两个学生对象,交学费
Stu tom = new Stu("tom");
tom.payFee(100);
Stu mary = new Stu("mary");
mary.payFee(200);
// 输出总方法
Stu.showFee();
}
}
class Stu{
private String name; // 普通成员
// 定义一个静态变量,累计学生的学费
private static double fee = 0;
public Stu(String name) {
this.name = name;
}
// 1.放方法使用了static修饰后,该方法就是静态方法
// 2.静态方法就可以访问静态变量
public static void payFee(double fee){
Stu.fee += fee;
}
public static void showFee(){
System.out.println("总学费:" + Stu.fee);
}
}
- 静态方法只能访问静态方法和静态变量
- 静态方法不能访问对象相关的关键字,比如this或者super,不能访问普通成员(非静态成员)
- 普通方法可以访问静态方法和静态变量
理解main方法语法
代码块
- 我们不管调用哪个构造器,都会优先调用代码块
- 对构造器的一种补充机制,可以初始化一些操作
- 代码块的调用顺序优先于构造器
- 代码快的使用细节
-static代码块是在类加载的时候执行的,而且只会执行一次 - 类加载的情况
1.创建一个对象实例的时候
2.子类继承父类,创建子类对象,优先加载父类
3.使用静态变量或者方法的时候
-普通代码块,在创建对象实例时会被隐式的调用,被创建一次就会调用一次,如果只是使用静态成员,普通代码块不会执行
-
普通代码块可以理解就是构造器的补充
-
细节4
-
创建一个对象时,在一个类的调用顺序
1.调用静态代码块和静态属性初始化:静态代码块和静态属性初始化是一样的,如果有多个静态代码块和多个静态变量初始化,按照定义的顺序调用
2.调用普通代码块和普通属性的初始化
3.调用构造方法
4.构造器的前面其实隐藏了super和普通代码块,静态相关的代码块和属性初始化时,在类加载时就执行完毕了
创建一个子类对象(继承)调用顺序
1.父类的静态代码块,父类的静态属性(同等优先级)
2.子类的静态代码块,子类的静态属性
3.父类的普通代码块,父类普通属性
4.父类的构造方法
5.子类的普通代码块,子类的普通属性
6.子类的构造器
package com.hspedu.codeblock_;
public class CodeDetail03 {
public static void main(String[] args) {
BBB bbb = new BBB();
}
}
class AAA{
private static int n1 = getN1();
private int n2 = getN22();
static int getN1(){
System.out.println("执行父类的静态方法getN1"); // 1
return 100;
}
static void printN1(){
System.out.println("执行父类的静态方法");
}
int getN22(){
System.out.println("执行父类普通方法getN2()"); //5
return 300;
}
static {
System.out.println("AAA父类的静态代码块"); // 2
}
{
System.out.println("AAA父类普通代码块"); // 6
}
public AAA(){
System.out.println("AAA 父类构造器被调用"); // 7
}
}
class BBB extends AAA{
private static int n1 = getN1();
private int n2 = getN2();
static int getN1(){
System.out.println("子类getN1静态属性"); // 3
return 100;
}
static void printn2(){
System.out.println("子类的静态方法");
}
int getN2(){
System.out.println("子类getN2的普通方法");//8
return 200;
}
static {
System.out.println("子类的静态代码块"); // 4
}
{
System.out.println("BBB子类普通代码块"); // 9
}
public BBB(){
System.out.println("BBB子类构造器方法"); // 10
}
}
单例设计模式
- 饿汉式单例模式
package com.hspedu.single_;
public class SingleTon01 {
public static void main(String[] args) {
// GirlFriend xh = new GirlFriend("小红");
// GirlFriend xb = new GirlFriend("小白");
// 通过类方法获取一个对象
GirlFriend instance = GirlFriend.getInstance();
System.out.println(instance);
}
}
// 有一个类,GirlFriend,只能有一个女友
class GirlFriend{
// 如何保证创建一个girlfriend
private String name;
// w为了能够在静态方法中使用,需要修饰为static
private static GirlFriend gf = new GirlFriend("小红红");
// 构造器私有化
// 2.在类的内部创建对象
// 3.提供一个公共的静态方法,可以返回gf对象
private GirlFriend(String name) {
this.name = name;
}
public static GirlFriend getInstance(){
return gf;
}
}
- 饿汉式可能导致创建了对象但是没有使用
package com.hspedu.single_;
/*
演示懒汉式
*/
public class SingalTon02 {
public static void main(String[] args) {
System.out.println(Cat.n1);
}
}
// 希望在程序运行过程中,只创建一个猫
class Cat{
private String name;
public static int n1 = 999;
// 步骤
//1. 构造器私有化
// 2.定义一个静态属性
// 3.使用public的static方法,可以返回一个Cat对象
private static Cat cat;
private Cat(String name) {
System.out.println("构造器调用");
this.name = name;
}
public static Cat getInstance(){
if(cat == null){
cat = new Cat("小可爱");
}
return cat;
}
}
- 饿汉式和懒汉式的区别
final关键字
final最后的最终的,可以修饰类,属性,方法,局部变量
final的用法
- 不希望类被继承,可以用final
- 不希望父类的方法被子类覆盖或者重写,用final
- 不希望父类的某个属性修改,用final
- 不希望某个局部变量修改,用final
package com.hspedu.final_;
public class Final01 {
public static void main(String[] args) {
E e = new E();
// e.TAX_RATE = 0.1;
// CC cc = new CC();
EE ee = new EE();
ee.cal();
}
}
// 如果我们使用A类不能被其他类继承
// 可以使用final修饰A类
final class A{
}
//class B extends A {}
class C {
public void hi(){
}
}
class D extends C{
@Override
public void hi() {
System.out.println("重写了父类方法");
}
}
class E{
public final double TAX_RATE = 0.08;
}
class F {
public void cry(){
final double NUM = 0.01;
// NUM = 0.9;
System.out.println("NUM=" + NUM);
}
}
class AA{
/*
定义的位置,在定义时
构造器
代码块
*/
public final int n1 = 1;
public final int n2;
public final int n3;
{
n3 = 1;
}
public AA(){
n2 = 3;
}
}
class BB{
/*
final修饰静态,初始化的位置只能是:
1.定义
2.在静态代码块
*/
public static final double TAX_RATE = 99;
public static final double TAX_RATE2;
static {
TAX_RATE2 = 4;
}
}
// final类不继承,但是可以实例化对象
final class CC{}
// 如果类不是final,但是含有final,该方法不能重写,但是可以继承使用
class DD {
public final void cal(){
System.out.println("123");
}
}
class EE extends DD{}
抽象类
- 模版设计模式
package com.hspedu.abstract_;
abstract class Template {
// 计算任务
public abstract void job();
public void calucateTime(){
// 得到开始的时间
long start = System.currentTimeMillis();
job();
//
// 得到结束的时间
long end = System.currentTimeMillis();
System.out.println("AA执行时间" + (end - start));
}
}