class Person
{
private String name1=null;
Person(String name)
{
name1 = name;
}
}
------<a href="http://www.itheima.com"target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
面向对象三大特性:封装,继承,多态。
封装
所谓封装就是将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。现实生活中这种现象非常普遍,电脑就是最显而易见的例子,它的内部事务非常复杂,常人难以掌握,不便于消费者使用,而且如果贸然改动会对机器造成安全隐患,这些都是厂商所不希望看到的,因此他们把计算机内部的内存,显卡,网卡,主板,以及错综复杂的线路等等用机箱封装起来,仅暴露出来鼠标键盘显示器音箱等公共方法供用户使用。而往机箱的每一个内部部件看,它的主板又包含了南桥北桥各种IO插口等元素,它也是封装了一部分特有功能,并向外暴露出公共访问的方式,这又体现了万物皆对象的哲理。
将对象封装起来的好处有很多,首先我们可以将变化隔离,这样便于外部使用(可以理解为让不懂发动机齿轮变速箱等工作原理的人也能开车)。同时提高重用性(使用的时候创建新对象即可),而且提高安全性。
具体的做法就是:把属性都隐藏,提供公共方法对其进行访问。因此在项目里这种形式很常见:一个private的属性XXX,对应两个相应的方法setXXX和getXXX,设置与获取。这是封装最基础的体现。
This关键字
当定义类中的功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
作用:可以用于区分局部变量和成员变量同名的情况。因为JAVA先在括号内(局部)找指定名称,如果找不到再到括号外找。所以下面这行代码就是一句废话。
class Person
{
private String name=null;
Person(String name)
{
name = name;
}
}
因为构造函数(Person)首先是一个函数,所以里面的变量name就是一个局部变量。我们想要修改的是成员变量name而非构造函数里的局部变量里的name。而name=name;两个都是构造函数中的局部变量。所以要在第一个name前加上this.关键字来标识它其实是成员变量name,也就是这个对象的name。
This的省略
其实类里面很多成员定义好了被使用,是由对象完成的,本类中的对象是this,因此如果构造函数里的String类型变量与成员变量不重名的话,其实前面是可以省略this的。如下:
class Person
{
private String name1=null;
Person(String name)
{
name1 = name;
}
}
第一个name的全称是this.name,Java会为我们自动加上。而如果重名了就不会加。
构造函数中的This
构造函数间调用只能用this语句,并且This语句只能定义在构造函数的第一行。因为初始化的动作要先执行,如果初始化中还有初始化则优先执行更细节的初始化。一个构造函数只执行一个this初始化。
另外一般函数不能直接调用构造函数。
单例设计模式(非常重要)
所谓设计模式就是程序猿们经过多年开发,归纳总结他们的经验教训得出来的解决某一类问题最行之有效的方法。以后开发就不要自作聪明,再摸着石头过河了,在解决这一类问题的时候就使用这一套方法就可以了。比如说学英语的方法各式各样,你可以捧着一个词典狂背,也可以完全置身于纯粹的英语环境,强迫自己与他人交流,但这些都不是最高效可行的方式,于是教育工作者和语言学家们经过多年总结,得出最有效的方式就是先学字母,然后学音标,学单词,学语法,学句子,学文章,慢慢地让学习者掌握一定程度的英语水平。
单例设计模式是Java中23种设计模式之一,它的意思是一个类只对应一个对象。它能确保对象的唯一性。
这在日后的开发中,尤其是多线程的开发中比较常见,比如说我们做某一个图书馆的书籍借阅管理系统。那么图书馆作为一个复杂事物肯定是一个类,而其内部的书要出要入,对象都必须且只能是这个图书馆,而不是世界上任意一所其他图书馆,因此要确保这个图书馆类只能建立一个图书馆对象,那么就需要用到单例设计模式。
单例设计模式的基本思想:
- 先禁止其他程序建立该类对象。
- 还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
- 为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
实现步骤:
- 将构造函数私有化。
- 在类中创建一个本类对象。
- 提供一个方法可以获取到该对象。
具体代码如下:
class Single
{
private Single(){}//1.将构造函数私有化。
private static Single s = new Single();//2. 在类中创建一个本类对象。
public static Single getInstance()//3.提供一个方法可以获取到该对象。
{
return s;
}
}
上面第二步之所以把Single s设置为静态的是因为构造函数私有了,所以无法创建该类的对象,而我们又必须获得该类的对象,因此需要使用静态类类型变量指向本类对象。这样就能在不通过外部主函数创建该类对象的情况下创建这个类的对象了(静态的加载先于对象的创建)。
上面三步是一个单例模式:不管有没有外部调用我的对象,我先初始化对象,称为:饿汉式。
此外,还存在着另一种思路,代码如下:
class Single
{
private Single(){}
private static Single s = null;
public static synchronized Single getInstance()
{
if (s == null)
s = new Single();
return s;
}
}
上面几步也是一个单例模式:对象当方法被调用时才初始化,也叫做对象的延时加载。称为:懒汉式,即没有人调用我的时候,我不创建对象,Single s指向空。只有当有人想获取我的对象的时候,我才创建一个对象给它。
这里需要注意一下线程的安全问题:上述代码第五行的synchronized是一个修饰符,表示线程同步。因为CPU的多线程处理,当有多个对象调用这个函数的时候可能会创建多个对象,因此需要加入synchronized使程序完全同步,确保不出错。原理是当某一个主函数中的命令访问该函数时该函数会锁住,其他调用无法访问,缺点是效率低,因为进入该函数之前都要判断一下是否有别的进程访问,没有才能进入函数。
而饿汉式函数里面就一句话,即使是多线程最少也不会把一句话再拆分。实际开发应该用饿汉式,简单高效。
因此上述代码的最完美方案是:
class Single
{
private Single(){}
private static Single s = null;
public static Single getInstance()
{
if(s==null)//这部分为了避免重复检查是否锁定,s有值了以后程序可以快速通过。
{
synchronized(Single.class)//锁定需要对象的存在,而静态进内存时,内存中尚未建立本类对象,但是一定有该类对应的字节码文件对象。对象是:类名.class
{
if (s == null)
//上面两行是为了确保安全,以防s为null的时候多线程混乱(多个线程同时进来创建多个对象)。
s = new Single();
}
}
return s;
}
}
在我们使用的时候,不管是饿汉式还是懒汉式,我们的类对于事物的描述方式还与以前相同,只是当需要将该事物的对象保证在内存中唯一时,就将以上三步加上即可,类里面的具体变量和方法,形式照旧。
饿汉式与懒汉式:
懒汉式:Single类进内存,对象还没存在,只有调用了getInstance方法时,才建立对象。
但获取对象是单例里面肯定要做的事情,先做后做都得做,所以开发一般都用饿汉式,因为简单,而且安全。
懒汉模式有个bug:因为CPU的多线程处理,当有多个对象调用这个函数的时候可能会创建多个对象,因此需要加入synchronized使程序完全同步,确保不出错。原理是当某一个主函数中的命令访问该函数时该函数会锁住,其他调用无法访问,缺点是效率低。
懒汉式面试常考到,里面还牵涉到了多线程的问题,考法很多样。