12.包装类的使用、static关键字、设计模式与单例模式、类的成员之四代码块

1.包装类的使用

1.1 为什么要有包装类

为了使得基本类型得变量具备类的特征
举例:
equals(Object obj)


ArrayList list = …;
list.add(Object obj)

add(int number)
add(double d)
add(boolean b)

1.2 有哪些包装类

在这里插入图片描述

1.3 基本数据类型、包装类、String之间的转换

  • 复杂的转换图
    在这里插入图片描述
  • 简化的转换操作
//1. 基本数据类型 ---> 包装类:调用包装类的构造器 ① Xxx(xxx x)  ② Xxx(String x)
    @Test
    public void test1(){
        int num = 10;

        Integer int1 = new Integer(num);
        System.out.println(int1.toString());

        float f1 = 12.3F;
        Float f2 = new Float(f1);
        System.out.println(f2.toString());

        String s1 = "123";
//        s1 = "123a"; //会报NumberFormatException数字类型转换的异常
        Integer int2 = new Integer(s1);
        System.out.println(int2.toString());

        boolean b1 = true;
        Boolean b2 = new Boolean(b1);
        System.out.println(b2.toString());

        String s2 = "true";
        s2 = "TruE";//结果为true
        s2 = "true1";// 编译通过,运行结果为:false
        Boolean b3 = new Boolean(s2);
        System.out.println(b3);

    }
    //2. 包装类 ---> 基本数据类型:调用包装类Xxx的xxxValue()
    @Test
    public void test2(){
        Integer int1 = new Integer(10);

        int i = int1.intValue();
        System.out.println(i);

        Boolean b1 = new Boolean(true);
        boolean b2 = b1.booleanValue();


        Double d1 = new Double(12.3);
        double d2 = d1.doubleValue();

    }
    @Test
    public void test3(){
        Account acct1 = new Account();
        System.out.println(acct1.balance1);//0.0
        System.out.println(acct1.balance2);//null

        System.out.println(acct1.isFlag1);//flase
        System.out.println(acct1.isFlag2);//null
    }

    //3. jdk5.0 新特性:自动的装箱、自动的拆箱
    @Test
    public void test4(){
        int num = 10;
        Integer int1 = num;//自动装箱
        System.out.println(int1.toString());
        Integer int2 = 20;//自动装箱

        Boolean b1 = true;//自动装箱

        int num2 = int1;//自动拆箱

        boolean b2 = b1;//自动拆箱

        Integer sum = int1 + int2; //自动拆箱 ---> 自动装箱

    }

    //4. 基本数据类型、包装类 ---> String: ① 与 "" 做连接运算 ② 调用String中重载的valueOf(xxx x)
    @Test
    public void test5(){
        int n1 = 10;
        //方式1:
        String s1 = n1 + "";
        //方式2:
        String s2 = String.valueOf(n1);

        boolean b1 = true;
        String s3 = String.valueOf(b1);

        System.out.println(s2);
        System.out.println(s3);

    }

    //5. String --> 基本数据类型、包装类:调用包装类的parseXxx(String s)
    @Test
    public void test6(){
        String s1 = "123";
        String s2 = s1 + 1; //结果为1231

        int i1 = Integer.parseInt(s1);
        int i2 = i1 + 1;//结果为124

        System.out.println(s2);
        System.out.println(i2);

        String s3 = "true";
        boolean b1 = Boolean.parseBoolean(s3);//结果为true
        s3 = "true1";
        boolean b2 = Boolean.parseBoolean(s3);
        System.out.println(b2);//false

        String s4 = "123a";
        //int i3 = Integer.parseInt(s4);//报NumberFormatException异常
        //System.out.println(i3);

        String s5 = "123.4";
        double d1 = Double.parseDouble(s5);
        System.out.println(d1);//123.4

        //int i4 = Integer.parseInt(s5);//报NumberFormatException异常
        //System.out.println(i4);

        String s6 = "123";
        double d2 = Double.parseDouble(s6);
        System.out.println(d2);
    }
  • 练习
    在这里插入图片描述
import java.util.Scanner;
import java.util.Vector;

/**
 * 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,
 * 并输出学生成绩等级。
 * <p>
 * 提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。
 * 而向量类java.util.Vector可以根据需要动态伸缩。
 * <p>
 * 创建Vector对象:Vector v=new Vector();
 * 给向量添加元素:v.addElement(Object obj);   //obj必须是对象
 * 取出向量中的元素:Object  obj=v.elementAt(0);
 * 注意第一个元素的下标是0,返回值是Object类型的。
 * 计算向量的长度:v.size();
 * 若与最高分相差10分内:A等;20分内:B等;
 * 30分内:C等;其它:D等
 *
 */
public class ScoreTest {

    public static void main(String[] args) {

        //1. 实例化Vector
        Vector v = new Vector();
        //2. 实例化Scanner
        Scanner scann = new Scanner(System.in);

        //3. 通过循环的方式,多次从键盘获取学生成绩
        int maxScore = 0;//记录最高分
        for(;;){
            System.out.println("请输入学生的成绩(以负数代表输入结束):");
            int score = scann.nextInt();

            //判断score是否是负数,如果是,退出循环
            if(score < 0){
                break;
            }

            //4. 调用Vector的addElement(Object obj)
            //方式1:
//            v.add(new Integer(score));//jdk5.0之前的做法
            //方式2:
            v.addElement(score);//自动装箱

            //5. 获取学生成绩的最高分
            if(maxScore < score){
                maxScore = score;
            }
        }
        //6. 遍历各个学生的成绩,并根据其与最高分的差值,计算等级
        for(int i = 0; i < v.size();i++){
            char grade;
            //jdk5之前的做法
//            Object obj = v.elementAt(i);
//            Integer int1 = (Integer) obj;
//            int score = int1.intValue();

            //jdk5及之后的做法
            int score = (int) v.elementAt(i);
            if(score >= maxScore - 10){
                grade = 'A';
            }else if(score >= maxScore - 20){
                grade = 'B';
            }else if(score >= maxScore - 30){
                grade = 'C';
            }else{
                grade = 'D';
            }
            System.out.println("student " + i +" score is " + 
            score + " grade is " + grade);
        }
    }
}

2.static关键字

  1. static:静态的
  2. static可以用来修饰:属性、方法、代码块、内部类。

2.1 static修饰属性

* 3. static修饰属性:
*      > 使用static修饰的属性,被类的多个对象“共享”
*      > static修饰的属性,在内存中只有一份:存放在静态域中(静态域存放在方法区中)
*         对比:不使用static修饰的属性,每个对象拥有一份,此属性存放在堆空间的当前对
* 象的内存空间里。
*      > 静态变量随着类的加载而加载
*        非静态变量随着对象的创建而加载
*      >  是否能够调用:(从生命周期的角度解释即可)
类变量实例变量
yesno
对象yesyes
* 4. 变量的分类: 4.1 按照数据类型分:基本数据类型  vs 引用数据类型
*                4.2 按照类中声明的位置:成员变量 (静态变量 vs 非静态变量 ;类变量 vs 实例变量)
*              局部变量(方法内、方法形参、构造器内、构造器形参、..)
*
*  思考: 开发中涉及一个类时,是否要将此属性设置为static的呢?
*         > 我们可以判断是否类的多个对象此属性的值需要是相同的,如果需要相同,则可以考虑共享。
*         > 开发中的一些常量有时常设计为static的。
*
*         比如:Math.PI , System.out

2.2 static修饰方法

 * 5. static修饰方法:静态方法
 *       > 随着类的加载而加载
 *       > 方法的调用 (从生命周期的角度解释即可)
静态方法非静态方法
yesno
对象yesyes
 *       > 非静态的方法内,可以调用当前类的非静态的属性、非静态的方法,也可以调用静态的属性、静态的方法
 *         静态的方法内,可以调用静态的属性、静态的方法,不能调用当前类的非静态的属性、非静态的方法
 *  *     比如:main() 、 Arrays工具类(Arrays.toString() / equals() / sort(int[] arr)/binarySearch())、
 *          Math的 random() \ sqrt() ; 项目一和项目二中的工具类
 *  *    思考: 开发中涉及一个类时,是否要将此方法设置为static的呢?
 *          > 后续设计相关的工具类的话,往往将其内部的方法声明为static的
 *          > 操作静态属性的方法,通常都是静态方法
  • 代码举例
public class StaticTest {
    public static void main(String[] args) {
        Chinese c1 = new Chinese();
        c1.name = "谷爱凌";
        c1.age = 20;
        c1.nation = "CHN";

        Chinese c2 = new Chinese();
        c2.name = "周杰伦";
        c2.age = 40;
        c2.nation = "中国";

        System.out.println(c1);
        System.out.println(c2);

        System.out.println(Chinese.nation);

//        System.out.println(Chinese.name);

        System.out.println(c1.name);
        System.out.println(c1.nation);

        //#############静态方法的使用####################
        c1.show();
        c1.info();

        Chinese.info();
//        Chinese.show();//编译不通过


        //#######################
        StaticTest.test2();
        test2();
    }

    public static void test2(){
        System.out.println("用于测试");
    }
}

class Chinese{
    //实例变量
    String name;
    int age;
    //类变量
    static String nation;//国籍

    @Override
    public String toString() {
        return "Chinese{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nation='" + nation + '\'' +
                '}';
    }
    //非静态的方法
    public void show(){
        System.out.println("name : " + name +", age : " + age);
        System.out.println("nation : " +nation);

        this.info();
    }

    public static void info(){
        //编译通过:可以调用静态的结构
        System.out.println("我是一个中国人");
        System.out.println("nation : " +nation);
        Chinese.test1();

        //编译不通过:不可以调用非静态的结构
//        System.out.println("name : " + name +", age : " + age);
//        show();

    }

    public static void test1(){
        System.out.println("用于测试");
    }

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

    public static String getNation() {
        return nation;
    }

    public static void setNation(String nation) {
        Chinese.nation = nation;
    }
}
  • 内存结构图

在这里插入图片描述
在这里插入图片描述

  • 练习
/*
 * static的应用举例
 *
 */
public class CircleTest {
    public static void main(String[] args) {
        Circle c1 = new Circle(1.3);
        Circle c2 = new Circle(2.3);

        System.out.println(c1);
        System.out.println(c2);

//        System.out.println(c1.total);
//        System.out.println(c2.total);
        System.out.println("创建的对象的个数为:" + Circle.getTotal());

        Circle c3 = new Circle();
        System.out.println(c3);
        System.out.println("创建的对象的个数为:" + Circle.getTotal());
    }
}

class Circle{
    private double radius;
    private int id; //自动累加赋值

    private static int init = 1001;

    private static int total;

    public Circle(double radius){
        this();
        this.radius = radius;
//        this.id = init++;
//        total++;
    }

    public Circle(){
        this.id = init++;
        total++;

    }

    @Override
    public String toString() {
        return "Circle{" +
                "radius=" + radius +
                ", id=" + id +
                '}';
    }

    public int getId() {
        return id;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public static int getTotal() {
        return total;
    }
}

3.设计模式与单例模式

 * 1. 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。
 *    设计模式免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。
 *  *  经典的设计模式一共23种:
 * 创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
 * 结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
 * 行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、
 * 备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
 * 2. 单例设计模式 : 保证在整个的软件系统中,对某个类只能存在一个对象实例
 *  * 3. 如何实现单例? 饿汉式 、懒汉式
 *  * 4. 对比饿汉式 、懒汉式
 *    从内存使用的上,懒汉式优于饿汉式。因为延迟了对象的创建,节省内存空间
 *    从线程安全性的角度上,饿汉式优于懒汉式。饿汉式线程安全,而懒汉式线程不安全。
  • 饿汉式
public class SingletonTest {
    public static void main(String[] args) {
//        Bank b1 = new Bank();
//        Bank b2 = new Bank();

//        System.out.println(Bank.bank);

        System.out.println(Bank.getInstance());
    }
}

//饿汉式
class Bank{

    //1. 私有化类的构造器
    private Bank(){

    }

    //2. 内部创建一个当前类的对象
    private static Bank bank = new Bank();

    //3. 提供get方法返回当前类的唯一实例
    public static Bank getInstance(){
        return bank;
    }
}
  • 懒汉式
public class SingletonTest1 {
    public static void main(String[] args) {
        Runtime r1 = Runtime.getInstance();
        Runtime r2 = Runtime.getInstance();

        System.out.println(r1 == r2);
    }
}

//懒汉式
class Runtime{
    //1. 私有化类的构造器
    private Runtime(){

    }

    //2. 声明当前类的一个变量
    private static Runtime instance = null;

    //3. 调用方法,返回当前类的一个实例
    public static Runtime getInstance(){
        if(instance == null){
            instance = new Runtime();
        }
        return instance;
    }

}

4.类的成员之四-代码块

/**
 * 类的成员之四:代码块(或初始化块)
 *
 * 1. 代码块的作用:用来初始化类或对象的信息
 *
 * 2. 代码块的分类:静态代码块 vs  非静态代码块
 *
 * 3.1 静态代码块:
 *    > 主要用来初始化类的信息
 *    > 内部可以有输出语句
 *    > 内部可以调用当前类中静态的属性、静态的方法,不能调用非静态的属性、非静态的方法
 *    > 随着类的加载而执行。因为类通常只加载一次,所以静态代码块也就只执行一次
 *    > 静态代码块的执行一定早于非静态代码块
 *    > 如果一个类中声明了多个静态代码块,则按照声明的先后顺序执行
 *
 * 3.2 非静态代码块:
 *    > 主要用来初始化对象的信息
 *    > 内部可以有输出语句
 *    > 内部可以调用当前类中静态的属性、静态的方法,也可以调用非静态的属性、非静态的方法
 *    > 随着对象的创建而执行。每创建一个类的对象,就会调用一次非静态代码块
 *    > 如果一个类中声明了多个非静态代码块,则按照声明的先后顺序执行
 *
 */
public class BlockTest {
    public static void main(String[] args) {

        System.out.println(Person.info);
        System.out.println();

        Person p1 = new Person();
        System.out.println();
        Person p2 = new Person();
    }
}

class Person{
    String name;
    static String info = "我是一个人";
    //静态代码块
    static{
        System.out.println("静态代码块2");
    }
    static{
        System.out.println("静态代码块1");
//        System.out.println(info);
//        System.out.println(name);//编译失败
    }

    //非静态代码块
    {
        System.out.println("非静态代码块2");
    }
    {
        System.out.println("非静态代码块1");

//        System.out.println(info);
//        System.out.println(name);

        name = "undefined";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值