从零开始学java(20)--- 方法重载,单例模式,final关键字与包装类

Day10

今天学习方法重载,单例模式,final关键字与包装类。

1.方法重载

在一个类中,方法名一样,但是参数列表(类型,数量,顺序)不同,方法重载,体现出OOP中的多态。

构造方法的重载:语法要求与普通方法的重载类似
一个构造方法可以调用重载形式的另外的构造方法:
语法: this(…); 只能出现在构造方法中,表示调用其他形式的构造方法。

说明:
1.参数列表不同包括:个数不同、顺序不同、类型不同。
注:仅仅参数变量名称不同是不可以的。
2.跟成员方法一样,构造方法也可以重载。
3.声明为final的方法不能被重载。
4.声明为static的方法不能被重载,但是能够被再次声明。

方法的重载的规则:

1.方法名称必须相同。
2.参数列表必须不同。
3.方法的返回类型可以相同也可以不相同。
4.仅仅返回类型不同不足以称为方法的重载。

2.设计模式之单例模式,

如果要求一个JVM中只允许有一个实例,这里说两种最简单的实现方式:

实现1:懒汉式(线程不安全)


  public class Singleton {
	private Singleton() {
	}

	private static Singleton singleton;

	public static Singleton getInstance() {
		if (singleton == null) {
			singleton = new Singleton();//在第一次调用的时候实例化自己   
		}
		return singleton;
	}
   }

实现2:饿汉式(性能问题)

  public class Singleton {
	private Singleton() {
	}
	//在类初始化时,已经自行实例化   
	private static Singleton singleton = new Singleton2();

	public static Singleton getInstance() {
		return singleton;
	}
}

3.final关键字

3.1 修饰变量

修饰属性(全局变量):可以在声明时赋值,或者构造方法赋值,或者在代码块中赋值。
修饰局部变量:方法参数,方法体中声明的变量。

对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象,也就是地址不可更改,但要注意的是地址中的内容是可以改变的。

变量不可更新其值,所谓的常量。
当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。

3.2 修饰方法:表示方法不可被子类重写

下面这段话摘自《Java编程思想》第四版第143页:

“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。“

因此,如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。

注:类的private方法会隐式地被指定为final方法。

3.3 修饰类:表示类不可被继承

当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。

3.4final和static

很多时候会容易把static和final关键字混淆,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。看下面这个例子:

public class Test {
    public static void main(String[] args)  {
        MyClass myClass1 = new MyClass();
        MyClass myClass2 = new MyClass();
        System.out.println(myClass1.i);
        System.out.println(myClass1.j);
        System.out.println(myClass2.i);
        System.out.println(myClass2.j);
 
    }
}
 
class MyClass {
    public final double i = Math.random();
    public static double j = Math.random();
}

运行这段代码就会发现,每次打印的两个j值都是一样的,而i的值却是不同的。从这里就可以知道final和static变量的区别了。

4.包装类

为什么需要包装类(Wrapper Class)
java并不是纯面向对象的语言,java语言是一个面向对象的语言,但是java中的基本数据类型却不是面向对象的,但是我们在实际使用中经常将基本数据类型转换成对象,便于操作,比如,集合的操作中,这时,我们就需要将基本类型数据转化成对象!所以Java 设计开始就提供了 8 种 基本数据类型及对应的 8 种包装数据类型。

包装类对基本数据进行封装,提供了若干方法对其操作,还有一些静态方法提供公共功能。

int Integer
short Short
byte Byte
long Long
char Character
float Float
double Double
boolean Boolean

包装类创建对象的方式就跟其他类一样。

Integer num1=new Integer(10);

自动装箱:基本数据类型可以自动转换为对应的包装类型
自动拆箱:包装类型可以自动转换为对应的基本类型

Integer  num1 = 10;		//自动装箱
int num2 = num1;		//自动拆箱

包装类中的缓存机制

创建包装类对象有两种方式:new关键字、valueOf()方法。
只要Integer类第一次被使用到,Integer的静态内部类就被加载,加载的时候会创建-128到127的Integer对象,同时创建一个数组cache来缓存这些对象。当使用valueOf()方法创建对象时,就直接返回已经缓存的对象,也就是说不会再新建对象;当使用new关键字or使用valueOf()方法创建小于-128大于127的值对象时,就会创建新对象。

所以我们使用包装类直接创建-128到127之间的对象时地址是相同。

public class Test {

	public static void main(String[] args) {
		Integer num1 = 10;
		Integer num2 = 10;
		Integer num3 = new Integer(10);
		Integer num4 = new Integer(10);
		Integer num5 = 128;
		Integer num6 = 128;
		System.out.println(num1 == num2);
		System.out.println(num3 == num4);
		System.out.println(num5 == num6);
	}

}

因此上面运行结果是true,false,false。

此外,在8种包装类型中,有缓存区的有Character、Byte、Short、Integer、Long,而且它们的实现方式基本一样,都是-128到127的缓存范围。Boolean虽然没有缓存区,但是因为只有两个值true、false,所以Boolean在成员变量中就创建了两个相应的对象。
没有缓存区的只有Float、Double,之所以没有原因很简单,即便是0到1这么小的范围,浮点数也有无数个,使用缓存区缓存它们不具备可能性和实用性。

缓存区的存在使得常用的包装类对象可以得到复用,这有利于提升性能。当我们需要创建新对象的时候再new一个,增加了灵活性。

更加详细关于包装类的知识大家可以去看一下JeremyChan1887的CSDN博客中关于Java中的包装类的介绍,以上有部分参考于其说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值