------- android培训、java培训、期待与您交流! ----------
一、 单例设计模式
所谓设计模式只是前辈们在编写代码的过程中总结出来的一些能够解决某些问题或者提高性能的思想,这里我们主要说单例设计模式
单例设计模式所能够解决的问题是什么呢? 那就是对象的唯一性问题。在生活中,有的时候我们只想某个事物不能够被太多人访问,并且我们限制每次只能又一个人访问,只有第一个人访问完了,下一个人才能访问,就是说这个对象是唯一的,操作它的只能是一个对象。
解决的办法是:
①不允许其他程序用new创建该对象:私有化该类构造函数
②在该类中创造一个该类实例:通过new在类中创建一个本类对象
③对外提供一个方法,让其他程序可以获取该对象:定义一个公有的方法,将创建的对象返回。
即:
class Single{
static Single s=new Single();//第二步动作
private Single(){}//第一步动作
public static Single getInstance(){
return s;
}//第二步动作
}
class SingleDemo{
public static void mian(String[] args){
Single s1=Single.getInstance();
Single s2=Single.getInstance();
System.out.println(s1==s2);
}
}
输出结果是:true
当我们想要将一个类设计成单例设计的模式,我们需要在类中加入以上三步动作即可。
单例设计模式包括两种:饿汉式单例设计模式与懒汉式单例设计模式,实现的不同之处如下所示:
①饿汉式:
class Person{
private static Person s=Person();
private Person(){}
public static Person getInstance(){
return s;
}
}
②懒汉式:也叫做延迟加载形式
class Person2{
private static Person2 s=null;
private Person2(){}
public static Person2 getInstance(){
if(s==null)
s=new Person2();
return s;
}
}
对于懒汉式,面试中应用的比较多,而在开发中饿汉式应用的比较多。因为懒汉式在做多线程的开发中会有一些问题。
懒汉式在多线程的开发中的安全隐患的解决方式:
class Person2{
static Person2 s=null;
private Person2(){}
public static Person2 getInstance(){
if(s==null){//在这里加判断是为了解决线程同步降低效率的问题,因为第一次加上锁后,其他线程再进来,一旦对象不为空,就可以直接返回对象不需要再加锁。
Syncronized(){//这里是为了在第一个线程上加锁
if(s==null)
s=new Person2();
}
}
return s;
}
}
二、方法重载与方法覆盖
方法重载又叫做Overload,是多态机制在一个类中的体现。主要表现在一个类的的多个方法的方法名完全相同,但是方法的参数个数以及参数类型不同会导致方法的返回值也不相同。
方法覆盖又叫做Override,是多台机制在拥有继承关系的两个类中的体现。覆盖了父类方法的子类的该方法必须与被覆盖的方法方法名,参数类型以及个数都完全相同,所以返回值也必须相同。
三、关于final,finally与finalize的区别
final是java中的一种关键字,可以把它修饰在属性、方法以及类上。当final被修饰在属性上的时候,表示该属性的内容不能够被改变,但是存储该属性的对象的地址是可以改变的。final被修饰在方法上的时候,表示该方法不能被覆盖,但是可以被重载。修饰在类上的时候,表示该类不能够被继承。
finally是java中异常处理机制的一个关键字代码块,必须配合try代码块使用。当finally一旦被使用后,程序到了最后就肯定会执行finally代码块中的内容,所以finally经常用来释放资源或者关闭连接。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。
四、权限访问修饰符详解
访问权限修饰符权限从高到低排列是public ,protected ,default, private。
权限修饰符权限图解
首先声明:java中,default这个修饰符并没有显式的声明,在成员变量和方法前什么修饰符也不用,默认的就是default。为了条理清晰,分三种不同情况来总结。
4.1 访问权限修饰符修饰成员变量和方法
public:表明该成员变量和方法是公有的,能在任何情况下被访问。
protected:必须在同一包中才能被访问。(说的比较简单,看个例子就明白了)
eg:
class A {
protected int weight;
protected int f( int a,int b ) {
// 方法体
}
}
假设B与A在同一个包中,则
class B{
void g() {
A a=new A();
A.weight=100;//合法
A.f(3,4); //合法
}
}
特别说明:什么是在同一个包中?
答:用package打包在一起的class ,叫在同一个包中。(不明白,举个例子)
eg:在JDK的src\java\io中,你会看到许多java类,第一句源代码都是package java.io;没有使用package打包的,在同一目录下的类也会被视做同一个包。
default:在这种情况下中,同protected。区别在第二和第三种情况中。
eg:
class A{
int weight
int f( int a,int b) {
// 方法体
}
}
private: 只能在本类中访问。
eg:
class Test {
private int money;
Test() {
money=2000;
}
private int getMoney(){
return money;
}
public static void main(String args[]) {
Test te=new Test();
te.money=3000; //合法
int m=te.getMoney(); //合法
System.out.println("money="+m);
}
}
PS: 实际上,把重要的数据修饰为private,然后写一个public的函数访问它,正好体现了OOP的封装特性,是OOP安全性的体现。
4.2 访问权限修饰符修饰类
1,不能用protected和private修饰类。
2,用default修饰的类叫友好类,在另外一个类中使用友好类创建对象时,要保证它们在同一包中。
4.3 访问权限修饰符与继承
这里的访问修饰符指的是修饰成员变量和方法。可以分为两种情况:
1,子类与父类在同一包中 ,此时只有声明为private的变量与方法不能被继承(访问)。
eg:
class Father{
private int money
int weight=100;
}
class Son extends Father{
viod f() {
money=10000;// 非法
weight=100; // 合法
}
}
2,子类与父类不在同一包中 ,此时private与default均不能被继承(访问), protected与public可以。
eg:
public class Father{
int height ;
protected int money=120;
public int weight;
protected int getMoney(){
return money;
}
void setMoney(int newMoney){
money=newMoney;
}
}
import com.aaa.Father;
public class Son extends Father {
void f(){
money=10000;//合法
height=170;//非法,height为default修饰的变量
System.out.println(money);//输出结果是10000
setMoney(300); //非法
int number=getMoney(); //合法
System.out.println(number);//输出结果是10000
}
public static void main(String args[]) {
Son sss=new Son();
sss.f();
}
}
五、子类的实例化过程详解
子类的实例化过程详细图解
class Fu{
Fu(){
System.out.println(“Fu run...”)
Show();
}
show(){
System.out.println(“hehe”);
}
}
class Zi extends Fu{
int num=9;//显示初始化
{
System.out.println(“show...”+num);
num=10;
}
Zi(){
Super();//隐含的
//此处还有显示初始化,隐含的
//还有构造代码块初始化,隐含的
System.out.println(“show...”+num);
}
Show(){
System.out.println(“show.....”+num);
}
}
如图所示,步骤如下(注意在子类构造函数中隐藏了super(),显示初始化以及构造代码块初始化的过程,但是我们要知道有):
①对象构造器先运行,此时已经进行隐式初始化,即此时num=0.先执行父类构造方法输出“Fu run...”和“show...0”
②显示初始化和构造代码块初始化,这都是隐含的,先进行显示初始化,所以输出“show...9”,然后在构造代码块中num被赋值为10。
③最后开始自定义构造函数的初始化,即输出“show...10”