java入门第八天

目录

类变量

类方法 

main方法

 代码块(初始化块)

代码块细节 

类加载3种场景⭐⭐⭐ 

代码块习题

单例设计模式

final关键字

final使用细节 

final应用实例 


类变量

  • 类变量也叫静态变量/静态属性
  • 基本语法:访问修饰符 static 数据类型 变量名
  • static变量会被类的所有对象共享
  • jdk7以后,类变量存储在类实例的最后(类实例在堆中),jdk7及以前是存储在方法区的静态域

如何访问类变量?

  • 类名.类变量名(更规范)
  • 对象名.类变量名 

类变量使用细节

  • 类变量与实例变量(普通属性)区别:类变量为所有对象所共享,实例变量是每个对象独享的
  • 加上static称为类变量或静态变量,否则为实例变量/普通变量/非静态变量
  • static类变量在类加载的时候就初始化了,即使没有创建对象也能使用

类方法 

  • 类方法也叫静态方法
  •  基本语法:访问修饰符 static 返回类型 方法名() { }

类方法的调用

  • 类名.类方法名 

类方法使用场景

当我们希望不创建对象也可以调用方法时,就可以使用静态方法。开发自己的工具类时,可以将方法定义为静态方法。

类方法细节

  • 类方法和普通方法都是随着类的加载而加载,结构信息存储在方法区
  • 类方法中无this的参数,普通方法中隐含着this的参数 
  • 类方法中不允许使用和对象有关的关键字,如this和super⭐
  • 类方法(静态方法)只能访问类变量和类方法(静态成员)⭐
  • 普通成员方法,既可以访问非静态成员,也可访问静态成员⭐
  • 静态方法要访问静态成员,必须先实例化一个对象,用该对象访问

Exercise1 

看看下段代码会输出什么 

package com.lili.static_;

public class StaticExercise01 {
    public static void main(String[] args) {
        new Test().count();
        new Test().count();
        System.out.println(Test.count);
    }
}

class Test {
    static int count = 9;
    public void count() {
        System.out.println("count = " + (count++));
    }
}

answer1:

count = 9

count = 10

11


 Exercise2

先看看有没有错误的代码,如有就将错误代码注释后,再看看输出

package com.lili.static_;

public class StaticExercise02 {
    public static void main(String[] args) {
        System.out.println("total = " + Person.getTotalPerson());
        Person person = new Person();
        System.out.println("total = " + Person.getTotalPerson());
    }
}

class Person {
    private int id;
    private static int total = 0;
    public static int getTotalPerson() {
        id++;
        return total;
    }

    public Person() {
        total++;
        id = total;
    }
}

answer2:

//id++; 静态方法不能访问非静态成员

输出:

total = 0

total = 1


Exercise3

 先看看有没有错误的代码,如有就将错误代码注释后,看看total最后等于多少

package com.lili.static_;

public class StaticExercise03 {
    public static void main(String[] args) {
        P.setTotal(4);
        new P();
    }
}

class P{
    private int id;
    private static int total = 0;
    public static void setTotal(int total) {
        this.total = total;
        P.total = total;
    }

    public P() {
        total++;
        id = total;
    }
}

answer3:

//this.total++ 静态方法中不能使用和对象有关的关键字

total = 5;


main方法

  1. main方法是java虚拟机调用,所以main方法的访问权限必须是public
  2.  java虚拟机在执行main方法时不必创建对象,所以main方法必须是static方法
  3. main方法中的String[] args参数,是在执行java命令时传递给所运行的类的参数,如:
java 执行的程序 参数1 参数2 参数3

 

idea中main动态传值


 代码块(初始化块)

属于类的成员,类似于方法,将逻辑语句封装在{}中,但和方法不同,没有方法名,没有返回,没有参数,不用通过对象或类显示调用,而是在类加载或创建对象时隐式调用

基本语法

[修饰符]{
    代码
};
  1. 修饰符可选,且只能为static
  2. 代码块分为静态代码块(static修饰)和普通代码块 
  3. 分号 ; 可以省略

代码块的好处和应用场景

  • 代码块相当于构造器的补充
  • 如果多个构造器中有相同的重复语句,就可以写到代码块中,提高代码的重用性
  • 每次调用构造器时,都会先调用代码块

代码块细节 

  • 静态代码块随类的加载而执行,普通代码块每创建一个对象就执行一次 

类加载3种场景⭐⭐⭐ 

  1. 创建对象实例时
  2. 创建子类对象时,父类也会被加载
  3. 使用类的静态成员时
package com.lili.codeblock;

public class CodeBlockDetail01 {
    public static void main(String[] args) {
        System.out.println("类加载的情况");
//        System.out.println("1 创建对象时");
//        A a = new A();
//        System.out.println("2 创建子类对象时,父类也会被加载,且先加载父类");
//        B b = new B();
        System.out.println("3 使用类的静态成员时");
        System.out.println(A.n);
    }
}

class B extends A{
    static {
        System.out.println("B的静态代码块被调用...");
    }
}

class A {
    public static int n = 999;
    static {
        System.out.println("A的静态代码块被调用...");
    }
}

注意:

static代码块是在类加载时执行,只会执行一次;

普通代码块每创建一次对象就执行一次 


  • 创建一个对象时,一个类中的调用顺序:

①先进行静态属性的初始化和静态代码块的执行,优先级一样,谁先定义调用谁;

②再进行普通属性的初始化和普通代码块的执行,优先级一样,谁先定义调用谁;

③最后调用构造方法。

package com.lili.codeblock;

public class CodeBlockDetail02 {
    public static void main(String[] args) {
        AA aa = new AA();
    }
}

class AA {
    private int n2 = getN2();
    private static int n1 = getN1();

    public AA() {
        System.out.println("构造器被调用...");
    }

    {
        System.out.println("AA的普通代码块被调用...");
    }

    static {
        System.out.println("AA的静态代码块被调用...");
    }

    public static int getN1() {
        System.out.println("n1初始化...");
        return 100;
    }

    public int getN2() {
        System.out.println("n2初始化...");
        return 200;
    }
}

  •  构造器的最前面其实隐含了super() 和 普通代码块的调用(默认调用父类无参构造器)

静态代码块和静态属性初始化在类加载时就执行,因此优先于普通属性初始化和普通代码块的调用 

下段代码,看看会输出什么?

package com.lili.codeblock;

public class CodeBlockDetail03 {
    public static void main(String[] args) {
        BBB bbb = new BBB();
    }
}

class AAA {
    {
        System.out.println("AAA的普通代码块...");
    }

    public AAA() {
        System.out.println("AAA的构造器...");
    }
}

class BBB extends AAA {
    public BBB() {
        //super();
        //调用普通代码块
        System.out.println("BBB的构造器...");
    }

    {
        System.out.println("BBB的普通代码块...");
    }
}

创建一个子类对象时,静态代码块和属性、普通代码块和属性、构造器的执行顺序如下:⭐⭐⭐

  • 父类的静态代码块、静态属性(优先级一样,按定义顺序执行)
  • 子类的静态代码块、静态属性(优先级一样,按定义顺序执行)
  • 父类的普通代码块和普通属性(优先级一样,按定义顺序执行)
  • 父类的构造器
  • 子类的普通代码块和普通属性(优先级一样,按定义顺序执行)
  • 子类的构造器
package com.lili.codeblock;

public class CodeBlockDetail04 {
    public static void main(String[] args) {
        //先进行类加载,再创建对象
        //1.1父类静态属性和代码块 1.2子类静态属性和代码块
        //2.1父类普通属性和代码块、构造器 2.2子类普通属性和代码块、构造器
        D d = new D();
    }
}

class C {
    static {
        System.out.println("C的静态代码块"); //1
    }
    private static int c1 = getC1();
    public static int getC1(){
        System.out.println("C的静态属性"); //2
        return 100;
    }
    private int c2 = getC2();
    public int getC2(){
        System.out.println("C的普通属性"); //5
        return 200;
    }
    {
        System.out.println("C的普通代码块"); //6
    }
    public C() {
        System.out.println("C的构造器"); //7
    }
}

class D extends C {
    private static int d1 = getD1();
    static {
        System.out.println("D的静态代码块"); //4
    }
    public static int getD1(){
        System.out.println("D的静态属性"); //3
        return 100;
    }
    private int d2 = getD2();
    public int getD2(){
        System.out.println("D的普通属性"); //8
        return 200;
    }
    {
        System.out.println("D的普通代码块"); //9
    }
    public D() {
        //super()
        //普通属性初始化、普通代码块
        System.out.println("D的构造器"); //10
    }
}

  •  静态代码块只能直接调用静态成员,普通代码块可以直接调用任意成员

代码块习题

test1

answer:类加载(调用类的静态成员时)时会执行静态代码块,static代码块只会执行一次

in static block!

total = 100

total = 100


test2

answer: 


单例设计模式

设计模式:是在大量实践基础上总结和理论化的优选的代码结构、编程风格和解决问题的思考方式。

  1. 单例设计模式:采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,且该类只提供一个获取对象实例的方法 
  2. 单例模式主要有2种:饿汉式、懒汉式

饿汉式、懒汉式实现步骤:

  1. 构造器私有化(防止在类的外部创建对象实例)
  2. 类的内部创建对象
  3. 向外暴露一个静态的公共方法getinstance(不用创建对象就可以获取)
package com.lili.single_;

public class SingleTon01 {
    public static void main(String[] args) {
        GirlFriend g1 = GirlFriend.getInstance();
    }
}

class GirlFriend {
    //饿汉式
    private String name;
    //1.构造器私有化
    private GirlFriend(String name) {
        this.name = name;
    }
    //2.创建一个static属性对象
    private static GirlFriend gf = new GirlFriend("gl");
    //3.提供一个公共的静态方法getInstance
    public static GirlFriend getInstance(){
        return gf;
    }
}

package com.lili.single_;

import javax.jws.soap.SOAPBinding;

public class SingleTon02 {
    public static void main(String[] args) {
        Cat cat = Cat.getInstance();
        System.out.println(cat);

        Cat cat2 = Cat.getInstance();
        System.out.println(cat2);

        System.out.println(cat == cat2);
    }
}

class Cat {
    private String name;
    private static Cat cat;
    //1.构造器私有化
    //2.定义一个static属性对象
    //3.提供一个public的static方法,返回对象

    private Cat(String name) {
        this.name = name;
    }

    public static Cat getInstance() {
        if (cat == null) {
            cat = new Cat("kitty");
        }
        return cat;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • 饿汉式:在类加载(3种情况)时就创建,即会有创建了但没有使用的情况,造成资源浪费!⭐
  • 懒汉式:要使用时才创建,懒汉式只有用户调用getInstance方法时才会创建对象
  • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  • 在JavaSE标准类中,java.lang.Runtime是经典的单例模式(饿汉式)

final关键字

final(最后的、最终的)可以修饰类、属性、方法和局部变量

final使用场景:

  1. 当不希望类被继承时
  2. 当不希望父类的某个方法被子类重写/覆盖时
  3. 当不希望类的某个属性值被修改时(常量名一般全大写)
  4. 当不希望某个局部变量被修改时
package com.lili.final_;

public class Final01 {
    public static void main(String[] args) {
        E e = new E();
        //e.PI = 8.0;
    }
}

//不希望A类被继承
final class A {
}

//class B extends A {
//}

class C{
    //不希望hi方法被重写
    public final void hi(){
    }
}

class D extends C{
//    @Override
//    public void hi() {
//        super.hi();
//    }
}

class E{
    //不希望属性PI被修改
    public final double PI = 3.14;
}

class F{
    public void method(){
        //不希望局部变量NUM被修改
        final double NUM = 0.01;
        //NUM = 0.99;
    }
}

final使用细节 

  1. final修饰的属性称为常量,一般用XX_XX_XX命名(下划线分隔)
  2. final常量必须赋初值(①定义时;②构造器中;③代码块中赋值)  
  3. 若final修饰的属性是静态的,则初始化的位置只能是:①定义时;②静态代码块中赋值
  4. final类不能继承,但是可以实例化对象
  5. 非final类中含有final方法,该类是可以被继承的,只是final方法不能被重写
  6. 如果一个类已经是final类,没必要将类中的方法修饰成final方法
  7. final不能修饰构造器
  8. final和static往往搭配使用,效率更高,使用static属性时不会导致类加载,底层编译器做了优化⭐⭐
  9. 包装类(Integer, Double, Float,  Boolean等都是final),String类也是final类

final应用实例 

编写一个程序,能计算圆的面积,圆周率为3.14,赋值的3个位置都写一下

package com.lili.final_;

public class FinalExercise01 {
    public static void main(String[] args) {
        double r = 2;
        Circle circle = new Circle(r);
        System.out.println("半径为" + r + "的圆面积:" + circle.calArea());
    }
}

class Circle {
    private double radius;
    //public final Double PI = 3.14;  //定义时赋值
    public final Double PI;

    public Circle(double radius) {
        this.radius = radius;
        //PI = 3.14;   //构造器中赋值
    }

    {
        PI = 3.14;  //代码块中赋值
    }

    public Double calArea() {
        return PI * radius * radius;
    }
}

  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是《Java基础入门第三版》的详细笔记: 1. Java语言特点 Java语言的特点有:简单易学、面向对象、平台无关性、安全性、高性能。 2. 基本数据类型 Java语言有8种基本数据类型:byte、short、int、long、float、double、char、boolean。 3. 运算符 Java语言提供的运算符有:算术运算符、关系运算符、逻辑运算符、位运算符。 4. 控制语句 Java语言提供的控制语句有:if语句、switch语句、for循环语句、while循环语句、do-while循环语句、break语句、continue语句。 5. 面向对象编程 Java是一种面向对象的编程语言,它支持类、对象、封装、继承和多态性等特性。 6. 异常处理 Java语言提供了异常处理机制,它可以帮助开发人员更好地处理程序中的错误和异常。Java语言中的异常处理包括:try-catch语句、finally语句、throws语句、throw语句。 7. 常用类库 Java语言提供了丰富的类库,常用的类库有:Math类、String类、StringBuffer和StringBuilder类、Date和Calendar类、File类和IO流等。 8. 数组 Java语言提供了数组来存储同种类型数据的集合,可以使用一维数组、二维数组等。 9. 字符串 Java语言中的字符串是一个类,它提供了很多方法来处理字符串,如字符串连接、截取、替换、比较等。 10. 输入输出 Java语言提供了IO流来处理输入输出,其中包括字节流和字符流,可以读取文件、网络等各种数据源。 以上就是《Java基础入门第三版》的详细笔记。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lili_1i1i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值