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