面向对象
概念:
面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。面向过程强调的是功能行为,例如把大象装进冰箱
1、打开冰箱。2、存储大象。
3、关上冰箱。
打开、存储、关上都是功能行为,在代码中的直观体现就是函数或者方法,这就是一种面向过程的以功能行为为主体的思想体现面向对象将功能封装进对象,强调具备了功能的对象,
还是大象装进冰箱的例子
1、冰箱打开
2、冰箱存储
3、冰箱关闭
所有的操作都是以“冰箱”为主体,而不是功能行为。也就是说冰箱自己已经具备打开、存储、关上的行为功能,我们只需要让冰箱执行它具备的功能就可以了。这就是一种面向对象的以执行功能的对象为主体的思想体现
特点:是一种符合人们思考习惯的思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者。其实就是不断的创建对象,使用对象,指挥对象做事情。
类与对象之间的关系
定义:生活中描述事物无非就是描述事物的属性和行为。如:人有身高,体重等属性,有说话,打球等行为,Java中用类class来描述事物也是如此。属性:对应类中的成员变量。
行为:对应类中的成员函数。定义类其实在定义类中的成员(成员变量和成员函数)。
成员变量和局部变量的区别
成员变量:1、成员变量定义在类中,在整个类中都可以被访问。
2、成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
3、成员变量有默认初始化值。
局部变量:
1、局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。
2、局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
3、局部变量没有默认初始化值。匿名对象匿名对象是对象的简化形式。
匿名对象两种使用情况:
1、当对对象方法仅进行一次调用时。
2、匿名对象可以作为实际参数进行传递。
创建对象,使用对象:
class Car {
String color = "红色"; //描述颜色
int num = 4; //描述轮胎数
void run() { //运行行为
System.out.println(color+".."+num);
}
}
class CarDemo {
public static void main(String[] args) {
Car c = new Car(); //创建一个对象,其实就是在堆内存中产生一个实体
c.color = "blue";
c.run();
Car b = c; //把c的引用赋值给b,b和c指向同一对象
b.num = 8;
b.run();
//new Car().color = "yellow"; //new Car()匿名对象
new Car().run();
show(new Car()); //将匿名对象作为实际参数传递
}
public static void show(Car c) {
c.color = "black";
c.num = 5;
c.run();
}
}
对象内存结构
只要是用new操作符定义的实体就会在堆内存中开辟一个新的空间,并且每一个对象中都有一份属于自己的属性。
通过对象.对象成员的方式操作对象中的成员,对其中一个对象的成员进行了修改,和另一个对象没有任何关系。
封装
概念:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
优点:
1、将变化隔离。
2、便于使用。
3、提高重用性
4、提高安全性
封装原则:
1、将不需要对外提供的内容都隐藏起来。
2、把属性都隐藏,提供公共方法对其访问。
/*
权限修饰符private:用于修饰类中的成员(成员变量,成员函数),只作用于本类中
所以对外就应该提供访问方式,访问方式中也能加入逻辑判断等语句
私有仅仅是封装的异种表现形式
*/
class Person1 {
private int age; //将age私有化以后,类以为建立了对象也不能访问
public void setAge(int a) { //设置年龄,并对年龄进行合理化的判断
if(a>0 && a<200) {
age = a;
speak();
}
else {
System.out.println("年龄输入错误");
}
}
public int getAge() { //把年龄返回给调用者
return age;
}
private void speak() {
System.out.println("age:"+age);
}
}
class PersonDemo1 {
public static void main(String[] args) {
Person1 p = new Person1();
p.setAge(-50); //调用输入年龄方法
}
}
构造函数
特点:
1、函数名与类名相同。
2、不用定义返回值类型。
3、没有具体的返回值。
作用:给对象进行初始化
注意:
1、当一个类中没有定义一个构造函数时,那么系统会默认给该类加入一个空参数的构造函数,类中自定义了构造函数后,默认的构造函数就没有了
2、多个构造函数是以重载的形式存在的。
什么情况下定义构造函数
当分析事物时,该事物存在具备一些特征或者行为,那么将这些内容定义在构造函数中
什么情况下定义构造函数
当分析事物时,该事物存在具备一些特征或者行为,那么将这些内容定义在构造函数中
class Person2 {
private String name;
private int age;
//定义一个Person2类的构造函数
Person2(String n,int a) {
name = n;
age = a;
System.out.println(name+","+age);
}
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
}
class PersonDemo2 {
public static void main(String[] args) {
Person2 p = new Person2("zach",18);//创建对象的时候就调用了构造函数给对象进行初始化,
p.setName("moli");
System.out.println(p.getName());
}
}
this关键字
概念:this代表其所在函数所属对象的引用,也就是说this代本类对象的引用。
什么时候使用this关键字?
当成员变量和局部变量重名,可以用关键字this来区分,this就是所在函数所属对象的引用。当在函数内需要用到调用该函数的对象时,就用this。this也可以用于在构造函数中调用其他构造函数
class Person3 {
private String name;
private int age;
Person3(int age) {
this.age = age; //使用this区分成员变量age与局部变量age
}
Person4(String name,int age) {
<span style="white-space:pre"> </span>this(name); //在构造函数中使用this调用其他 构造函数,但只能定义在构造函数第一行,因为初始化动作要先执行
<span style="white-space:pre"> </span>this.age = age;
<span style="white-space:pre"> </span>}
//定义一个方法来判断两个人的年龄是否相同
public boolean compare(Person3 p) {
return this.age == p.age;
}
}
class PersonDemo3 {
public static void main(String[] args) {
Person3 p1 = new Person3(26);
Person3 p2 = new Person3(20);
System.out.println(p1.compare(p2));
}
}
static关键字
static关键字用于修饰成员变量和成员函数
特点:
1、随着类的加载而加载。
2、优先于对象存在。
3、被所有对象所共享。
4、可以直接被类名调用。
class Person1 {
String name;
static String country = "CN"; //静态变量(类变量),对象的共享属性用static修饰
public void show() {
System.out.println(country+","+name);
}
}
class StaticDemo1 {
public static void main(String[] args) {
Person1 p = new Person1();
System.out.println(p.country);//可以直接被类名调用(Person.country)
}
}
成员变量和静态变量的区别?
1.两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2.调用方式不同
静态变量随着类的加载而存在,随着类的消失而消失。
2.调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3.别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
4.数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
注意:
1.静态方法只能访问静态成员,如果访问非静态成员,就会报错!
原因:静态方法和变量存在的时候,对象还不存在,非静态变量也不存在,肯定无法访问。
2.同理静态方法中不可以写this、super关键字
class Person {
String name;
static String country = "CN";
public static void show() { //静态方法
System.out.println(country+name); //此处访问了非静态成员name
}
}
静态什么时候使用?
1.静态变量当分析对象中所具备的成员变量的值都是相同时,这时这个成员就可以被静态修饰。
只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的
如果是相同的数据,对象不需要做修改,是需要使用即可,不需要存储在对象中,定义成静态的
2.静态函数
函数是否用静态修饰,就参考一点,就是该函数功能是否需要访问 到对象中的特有数据
简单说,从源代码看,该功能是否需要访问非静态成员变量,如果需要,该功能就是非静态的
如果不需要,就可以将该功能定义成静态,当然,也可以定义成非静态,但是非静态需要被对象调用
如果没有访问特有数据的方法,该对象的创建时没有意义的
静态代码块:随着类的加载而执行,而且只执行一次
作用:用于给类进行初始化
class Person2 {
int age;
static int num = 5;
public static void speak() {
System.out.println(num);
}
public void show() {
System.out.println(age);
}
}
public class StaticDemo2 {
public static void main(String[] args) {
Person2.speak();
}
}
单例设计模式
设计模式:对问题行之有效的解决方式,其实,它是一种思想。
单例设计模式作用:是可以保证一个类在内存中的对象唯一性,比如多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
如何保证对象唯一性呢?
1、不允许其他程序用new创建该类对象。
2、在该类创建一个本类实例。
3、对外提供一个方法让其他程序可以获取该对象。
饿汉式:
class Single {
public static void main(String[] args) {
SingleDemo s1 = SingleDemo.getInstance(); //调用getInstance()方法来创建对象
SingleDemo s2 = SingleDemo.getInstance();
s1.setNum(29);
System.out.println(s2.getNum());
}
}
class SingleDemo {
private int num;
public void setNum(int num) {
this.num = num;
}
public int getNum() {
return num;
}
//私有化构造函数,让本类以外的类不能创建该类对象
private SingleDemo() {
}
static SingleDemo s = new SingleDemo(); //在本类中创建一个对象
//通过公有方法,将创建的对象的引用返给调用者
public static SingleDemo getInstance() {
return s;
}
}
饿汉式内存示意图:
懒汉式:
class SingleDemo2 {
private SingleDemo2() {
}
private static SingleDemo2 s = null;
public static SingleDemo2 getInstance() {
if(s == null)
s = new SingleDemo2();
return s;
}
}
饿汉式与懒汉式的区别:
饿汉式SingleDemo类一加载就在内存中建立对象。懒汉试SingleDemo类加载后,对象还没存在s在方法区的值为null,知道调用getInastance()方法