一、 面向对象的概念
1.1、 理解面向对象
面向对象时相对于面向过程而言,面向对象和面向过程都是一种思想。
面向过程:强调的是一种功能行为;
面向对象:将功能装进对象,强调具备功能的对象。
面向对象时基于面向过程的。
面向对象的三个特征:封装,继承,多态
开发:其实就是找对象使用,没有对象,就创建对象。
找对象,建立对象,使用对象,维护对象的关系。
类和对象的关系:
类就是对现实生活中事物的描述。
对象: 就是这类事物,实实在在存在的个体。
映射到java中,描述就是class定义的类,
具体对象就是对应java在堆内存中用new建立的实体。
1.2、 类与对象的关系
类与对象的关系如图所示:
可以理解为:
类就是图纸;
汽车就是堆内存中的对象。
例:需求:描述汽车(颜色、轮胎数),描述类就是描述事物的属性和行为。
属性对应类中的变量,行为对应类中的函数(方法)。
其实定义类就是在描述事物,就是在定义属性和行为,属性和行为共同成为类中的成员(成员变量和成员方法)。
class Car
{
String color = "蓝色"; //描述颜色;
int num = 4; //描述轮胎数;
void run()
{
System.out.println(color+"..."+num);
}
}
class CarDemo1
{
public static void main(String[] args)
{
//生菜汽车,通过new操作符在堆内存中创建一个实体;
Car c = new Car(); //c为一个类类型变量,类类型变量指向一个对象;
c.color = "红色"; //将汽车颜色改为红色;java指挥方式:对象.对象成员;
c.run(); //让汽车运行起来;
}
}
成员变量和局部变量的区别:
1)、成员变量作用在整个类中;局部变量作用于函数中,或者语句中。
2)、成员变量在堆内存中,因为对象的存在,才在内存中存在;而局部变量存在于栈内存中。
1.2、匿名对象
匿名对象是对象的简化形式。
匿名对象两种使用情况:
1).当对对象方法只进行一次调用时;如果对一个对象进行多个成员调用,就必须给这个对象起个名字。
2).匿名对象可以作为实际参数进行传递。
示例:
class Car
{
String color = "红色";
int num = 4;
void run()
{
System.out.println(color+"..."+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
show(new Car()); //利用一个匿名对象进行实参传递;
}
public static void show(Car c)
{
c.num = 5;
c.color = "蓝色";
c.run();
}
}
二、 封装(Encapsulation)
2.1、封装的概念
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:1)、将变化隔离;
2)、便于使用
3)、提供复用性;
4)提高安全性。
封装原则:1)、将不需要对外提供的内容隐藏起来;
2)、把属性都隐藏,提供公共方法对其访问。
2.2、private关键字
private:私有,权限修饰符,用于修饰类中的成员(成员变量,成员函数),私有只在本类中有效。
注意:私有仅仅是封装的一种表现形式。
之所以提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句,对访问的数据进行操作,以提高代码的健壮性。
示例:
class Person
{
private int age;
public void setAge(int age)
{
if(age>0 && age<130) //对age进行逻辑判断,以提高age的安全性;
{
this.age = age;
show();
}
else
System.out.println("非法年龄!!!");
}
public int getAge()
{
return age;
}
void show()
{
System.out.println("age = "+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
//p.age = 20; 由于age被私有化,所以不能直接被访问
p.setAge(20);
}
}
三、 构造函数
3.1、构造函数特点
1、函数名与类名相同;
2、不用定义返回值类型;
3、不可以写return语句。
作用:对象一建立就会调用与之对应的构造函数,所以可以给对象进行初始化。
注意:1、默认构造函数的特点;
2、多个构造函数是以重载的形式存在的。
构造函数的小细节:当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。当在类中定义了构造函数后,默认的构造函数就没有了。
构造函数与一般函数在写法上有所不同,在运行时也有不同:构造函数是在对象一建
就运行,给对象初始化;而一般方法是在对象调用时才执行,给对象添加对象具备的功能。
一个对象建立,构造函数只运行一次;而一般方法可以被该对象调用多次。
什么时候定义构造函数呢?
当分析事物时,该事物存在就具备一些特性或者行为,那么将这些内容定义在构造函数中。
3.2、构造代码块
作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行。
构造代码块与构造函数的区别:构造代码块是给所有对象进行统一初始化。而构造函数只给对应的对象初始化。
构造代码块中定义的是不同对象共性的初始化内容。
四、 this关键字
this:代表本类的对象
this代表它所在函数所属对象的引用。
简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。但凡本类功能内部中使用了本类对象,都用this表示。
class Person
{
private int age;
public void setAge(int age)
{
if(age>0 && age<130) //对age进行逻辑判断,以提高age的安全性;
{
this.age = age;
show();
}
else
System.out.println("非法年龄!!!");
}
public int getAge()
{
return age;
}
void show()
{
System.out.println("age = "+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
//p.age = 20; 由于age被私有化,所以不能直接被访问
p.setAge(20);
}
}
this语句:用于构造函数之间互相调用。
this语句只能定义在构造函数的第一行。(初始化动作要先执行)
示例:
Person(int age)
{
this.age = age;
}
Person(String name,int age)
{
this(age); //this语句用法;且此语句只能定义在构造函数第一行;
this.name = name;
}
五、 static(静态)关键字
5.1、static关键字:用于修饰成员(成员变量和成员函数)
被修饰的成员有以下特点:
1.随着类的加载而加载
也就是说:静态会随着类的消失而消失,说明它的生命周期最长;
2.优先于对象存在;
静态是先存在的,对象时后存在的。
3.被所有的对象所共享;
4.当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外还可以直接被类名所调用。类名.静态成员
5.2、使用注意事项:
1.静态方法只能访问静态成员;
2.静态方法中不可以写this,super关键字;
3.主函数是静态的。
5.3实例变量和类变量的区别:
1.存放位置:
类变量随着类的加载而存在于方法去区中;
实例变量随着对象的的建立而存在于堆内存中。
2.生命周期:
类变量生命周期最长,随着类的消失而消失;
实例变量生命周期随着对象的消失而消失。
5.4、静态的利弊
利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份。可以被类名直接调用。
弊:生命周期过长,访问出现局限性。(静态虽好,只能访问静态)。
5.5、主函数
public static void main(String[] args)
主函数:是一个特殊的函数,作为程序的入口可以被jvm调用。
主函数的定义:
public:代表着该函数访问权限是最大的。
static:代表着主函数随着类的加载就已经存在了。
void:主函数没有具体的返回值。
main : 不是关键字,但是是一个特殊单词,可以被jvm识别。
(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。
主函数是固定格式的:jvm识别。
jvm在调用主函数时,传入的是new String[0].
5.6、什么时候使用静态?
1)、当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中。
2)、当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的.
5.7、静态代码块
格式:
Static
{
静态代码块中要执行的语句;
}
特点:随着类的加载而执行,只执行一次,并优先于主函数。
用于给类进行初始化。
静态代码块给类初始化;
构造代码块给对象初始化;
构造函数给对应对象初始化。
5.7、对象初始化过程
Person p = new Person(“zhangsan”,20);
此语句的初始化过程:
1)、因为new用到了Person.class,所以会先找到Person.class文件加载到内存中;
2)、执行到该类中的static代码块(如果有的话),给Person.class类初始化;
3)、在堆内存中开辟空间,分配内存地址;
4)、在堆内存中建立对象的特有属性,并进行默认初始化;
5)、对属性进行显示初始化;
6)、对对象进行构造代码块初始化;
7)、对对象进行对应的构造函数初始化;
8)、将内存地址赋给栈内存中的p变量。
六、 单力设计模式
设计模式:解决某一类问题最行之有效的方法。
java中23种设计模式:
单例设计模式:解决一个类在内存中只存在一个对象。
想要保证对象唯一:
1. 为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象。
2. 还为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象。
3. 为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三步的代码体现:
1. 将构造函数私有化;
2. 在类中创建一个本类对象;
3. 提供一个方法可以获取到该对象。
饿汉式:先初始化对象
Single类一进内存就创建对象。
eg:
class Sigle
{
private static Single s = new Single();
private Single(){}
private static Single getInstance()
{
return s;
}
}
懒汉式:对象是方法被调用时才初始化,也称为对象的延时加载。
Single类进了内存,对象还没有建立,只有调用了getInstance方法是才建立对象。
eg:
class Single
{
private static Single s = null;
private Single(){}
private static Single getInstance()
{
if(s == null)
{
synchronized(Single.class)
{
if(s == null)
s = new Single();
}
}
return s;
}
}