面向对象-封装

 
1. 面向对象的理解:

特点:1. 面向对象就是更符合人们思考习惯的一种思想。

          2. 从面向过程的执行者,转变成了面向对象的指挥者

3. 面向对象将复杂的事情简单化了。

4. 在实现功能,先找java当中是不是提供好了相关的对象,没有对象自己造一个对象。比如说公司招聘人员找不到人的 时,这时公司就需要自己在公司内部培养人,也就是自己造对象。

其实面向对象是一种思想,是面向过程而言,将复杂的事情变的更简单了。

通过把大象放到冰箱里这个列子来理解面向对象的概念:

面向过程:把冰箱门打开、存储大象、关闭冰箱;强调的过程注重行为;

面向对象:冰箱.打开、冰箱.存储、冰箱.关闭;强调的是冰箱这个对象。

 ★面试题:你怎么理解面向对象?

首先说面向对象的特点:它是一种思想,它让复杂的问题简单化,它把执行者变成了指挥者。

然后举例子来说明,最猛的就是结合实际场景来说:其实面试官你就是在用面向对象的思想在思考问题,为什么这么 说?因为公司业务蒸蒸日上,需要招更多的人来完成项目,所以才在这里招聘人员,你需要找一些具备专业编程经验的人,来 帮公司完成工作,那么我就是那个对象,因为我具备专业编程能力,你就是那个指挥者,指挥我来做事,至于我怎么去完成编 程任务,你是不需要去知道,你只要结果了就可以了,这其实就是把你之前的工作简化了,你不必再事必躬亲了。这就是面向 对象思想的体现。

同时可以结合去饭店吃饭,在家做事等等列子来说明面向对象的思想。


2. 类和对象关系:

1. 类到底是什么?
类就是对现实生活中事物的描述,描述中包含了该类事物的共性内容。

          	class Car {
			String color;
			int  num;
			void  run() {  }
		}

在类中定义的变量和函数都称为类中的成员。

成员:成员变量---属性;

成员函数---行为:

  如上面代码中,num和color是成员属性;而run()是成员函数。

2. 什么是对象?

对象就是该类事物实实在在存在的个体。

Eg:现实生活中的对象:张三、李四

想要描述:提取对象中的共性内容,对具体的抽象。

描述时:这些对象的共性有姓名、年龄、性别、学习java的功能。

对象也可以理解为其实就是个容器,用来存储更多的数据,存储的都是每一个对象特有的数据,而类就是这些数据所属 的属性。

如:用java语言来描述一个小汽车;描述事物:无非就是描述事物的属性和行为;属性:轮胎数、颜色;行为:运行

			class Car{
				String color="red";
				int num=4;
				void run(){
					system.out.println(color+""+num);
				}
			}
			class CarDemo{
				public static void main(String[] args){
					Car c=new Car();
					c.color="bule";
					c.num=5;
					c.run();
 					Car c1=new Car();
					c1.num=8;
					c1.color="green";
					c1.run();
				}	
			}

 重点:分析上述代码在内存中的分布:

3. 成员变量和局部变量的区别:

1. 源代码中定义位置不同:

成员变量:定义在类中,在整个类中有效。

局部变量:定义在函数中,在局部范围内有效。

简单一句话:作用范围不一样,成员变量作用于整个类中,局部变量作用于函数中,或者语句中。

2. 在内存中的位置和事件不同:

生命周期不同:

成员变量:随着对象的创建的而出现在堆内存中,随着对象被回收而消失。

局部变量:随着变量所属局部区域的运行,而出现在栈内存中,随着所属区域运行结束而释放。

3. 变量使用的初始化:

成员变量:因为堆内存中都有默认初始化值,对于引用型变量默认值就是null;

局部变量:因为在栈内存中都没有默认初始化值,必须手动初始化后才可以参与运算。

4. 匿名对象:即没有名字的对象,简化书写用的。

基本使用:1. 当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化,如果对一个对象进行这个成员的调用,必须给这个对象起个名字;

2. 可以将匿名对象作为实际参数进行传递;一旦对对象进行多个成员操作时,必须要对对象起个名字。

			public static void main(String[] args){
					show(new  Car())
				}
				public  static void show (Car c){
					c.num=3;
					c.color="back";
					c.run();
				}


5. 面向对象三个特征:封装、继承和多态。

1.封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式,凡是面向对象必须有封装性。

特点:1. 将变化隔离; 2. 便于使用; 3. 提高复用性; 4. 提高安全性。

原则:1. 将不需要对外提供的内容都隐藏起来; 2. 把属性都隐藏,提供公共方法对其访问。

在代码中的体现:1.将成员变量都私有化,并通过共有的方法对其进行访问,这两个方法是:setXxx和getXxx;

2.只要不准备对外提供的全部都封装起来;

3. 私有仅仅是封装的一种表现形式,函数是最小的封装体,类也是封装体。

★方法需要私有吗?

			public  static  void  selectSort(){
					swap();
				}
				private void swap()  {  }    //此处私有是因为位置置换不用提供给用户;

代码实现:

			class Person{
					private int age;//为了不让其他程序直接访问age属性,避免错误的数据,可以使用一个关键字来完成private私有,它是一个权限修饰符。
					public void setAge() {    //对外提供函数是可以控制你输入的参数。
						//一个成员变量通常对应的两个方法、
						if(a>130||a<0)  {
							age=a;
							speak();
						}	
						else
							system.out.println();
					}
					public void getAge()  {
						return age;
					}
 					void speak()  {
						sop();
					}
				}
				class PersonDemo {
					public static void main(String[] args) {
						Person p=new  Person();
						p.age=-20;//错误数据是因为对象直接访问age属性造成的。
						p.speak();
					}
				}

总结:凡是set开头的返回值类型是void,get开头的跟它的返回值类型一致。

6. 构造函数:用于给对象初始化的;

1.特点:1.函数名固定,与类名相同;

  2.不需定义返回值类型;

3.不可以写return语句。

2.作用:给对象进行初始化;对象一建立,就会调用与之对应的构造函数对其进行初始化。

3. 小细节:当一个类中无构造函数时,系统会自动给该类加上一个空参数的构造函数;如果在该类中定义了具体的构造函数,那么系统默认的空参构造函数就没有了。

4.构造函数和一般函数的区别:

1.格式上的不同:构造函数格式为 修饰符类名(参数列表){};而一般函数格式为 修饰符 返回值类型 自定义函数名(参数列表){}

2. 运行上不同:构造函数是在对象已经建立就执行对应的构造函数,给对象进行初始化。而一般函数是在对象创建后,再被调用。

3. 作用不同:构造函数是对对应对象进行初始化的,叫做对象已建立时要做什么事情;而一般函数是给对象提供更多的功能,方便与对象的调用。

4. 调用次数不同:构造函数是对象创建时,就调用一次,因为初始化动作最先执行,只执行一次;而一般函数在对象创建后,可以被多次调用。

5.什么时候定义构造函数?

当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中;如在描述人的时候,人有自己的属性姓名、年龄等,如果要一创建人类对象的时候就要对象有姓名、有年龄,这个时候就可以定 义一个带name和age参数的构造函数,来对对象进行初始化,使其一创建就有name和age。

6. 构造函数内部的初始化顺序:默认初始化>显示初始化;默认初始化始终是第一位。

7. 注意:如果构造函数中存在判断语句,可以加return语句,作用是结束语句;如果将构造函数加上void,则不再是构造函数而是一般函数。

7.构造代码块:定义在类中,是一个独立的代码块,作用是给所有对象进行初始化的,在构造函数之前执行。

  和构造函数的区别:构造代码块是给所有对象初始化;而构造函数是给对应的对象初始化。

和局部代码块的区别:局部代码块是定义在函数中,用来定义变量的声明周期。


8.this关键字:看上去是用来区分成员变量和局部变量;

1.用于:当成员变量和局部变量重名的时候,为了区分这种情况我们可以使用this关键字来完成;它代表的是当前对象的引用,自己本身不是一个对象,仅仅是一个本类对象的引用。

  2.应用:给人定义一个用于比较年龄是否相同的方法,代码体现如下:

			 class   Person{
				public  boolean  compare(Person  p){
					return  this.age==p.age;//用到了本类对象,用this来表示。
				}
			}
 			class PersonCom{
				public static void main(String[] args){
					Person p1=new Person(20);
					Person p2=new Person(25);
					boolean  b=p1.compare(p2);
					System.out.println(b);
			}
总之,当定义类中功能时,该函数内部要用到该函数的对象时,这时用this来表示这个对象。
3.构造函数间的调用:
构造函数中调用其他构造函数的this() 语句必须定义在构造函数的第一行,因为构造函数是用来初始化的;初始化的动作必须先执行。

                    如:Person(String name){
				this.name=name;
			}
			Person(String name,int age){
				this(name);//p(name)
				this.age=age;
			}
注意:1.this()语句只能放在构造函数的第一行,这是规则; 2. 函数中不允许两个构造函数一直循环调用; 3. 一般函数不能直接调用构造函数。


9.静态(static):当多个对象中存在共享数据是使用它修饰;它是修饰成员的修饰符,它所修饰的成员变量的数据被对象所共享;当成员被static修饰后,就多了一种调用方式,除了被对象调用外,还可以直接被类名调用,格式为 类名. 静态成员,即没有对象仍然可以调用。

1.静态特点:1. 静态随着类的加载而加载,随着类的消失而消失,生命周期最长;

2. 被所有对象所共享;

3.优先于对象存在;

4. 可以直接被类名调用;

2.好处:对对象的共享数据进行单独空间(方法区)的存储,节省空间,没必要每个对象中都存储一份,可以直接被类名调用。

3.弊端:生命周期过长;访问出现局限性,静态只能访问静态。

4.类变量(静态)和实例变量(非静态)的区别:

1.存储位置:类变量随着类的加载而存在于方法区中;而实例变量随着对象的创建存在于堆内存中;

2.生命周期:类变量随着类的消失而消失,生命周期最长;而实例变量随着对象的消失而消失。

5.使用注意事项:

1.静态方法只能访问静态成员,非静态的方法可以访问静态成员,也可以访问非静态成员;

2.静态方法不可以定义this,super关键字,因为this,super都代表对象的引用,而静态是优先于静态存在的;

3.主函数也是静态的,它是特殊函数,格式是固定的,能被jvm识别。

6.什么时候使用静态?因为静态是修饰成员的,所以从两方面下手:

1.成员变量:当对象中出现共享数据(值)时(注意是值共享,如人都有姓名这个属性,但姓名属性值不一样,张三、李四等,所以不能共享)该数据被静态修饰;而对象中的特有数据需定义为非静态的存储在堆内存中;

  2.成员函数:当方法中没有访问到对象的特有数据时,就可以定义为静态方法,用static修饰。

7.静态代码块:
1. 特点:无法调用,随着类的加载而执行,且仅执行一次。和主函数在同一个类中,优先于主函数运行; 格式:  static { 执行语句 }
    2. 作用:可以给类进行初始化。

3. 注意:1.若类中所有方法都是静态的,则可以私有构造函数以免创建对象浪费空间。

2. 若不希望静态变量随意修改,可以将其私有,此时再把构造函数私有,这样外部就不能对其修改,只有内部类中的方法才可以修改变量的值。

4. 对象的初始化顺序:父类静态内容>子类静态内容>父类非静态代码块>父类构造代码块>父类构造函数>子类非静态代码块>子类构造代码块>子类构造函数,代码体现如下:

                        class   Person {
				private String name;
				private int age;
				private static String country="cn";
				Person(String name,int age) {
					this.name=name;
					this.age=age;
				}
				public void setName(String name) {
					this.name=name;
				}
				public void speak() {
					System.out.println(this.name+"..."+this.age);
				}
				public static void showCountry() {
					System.out.println("Country="+country);
				}
			}
			class PersonDemo {
				public static void main(String[] args) {
					Person p=new Person("lisi",21);
				}
			}
过程如下:Person p=new Person()做的事:

1.因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中;

2.执行该类中的静态代码块,若有的话,给Person类进行初始化;

3.在堆内存中开辟开辟空间,分配内存地址;

4.在堆内存中建立对象的特有属性,并进行默认初始化;

5.对属相进行显示初始化;

6.对对象进行构造代码块初始化;

7.对对象进行构造函数初始化;

8.将内存中地址赋给栈内存中的p变量。


10. 单例设计模式:保证一个类中对象的唯一性;

想要保证唯一:1. 为了避免程序过多建立该类对象,先禁止其它程序建立该类对象;

2. 为了让其它程序可以访问到该类对象,只好在本类中自定义一个对象;

3. 为了方便其它程序对自定义对象访问,可以提供一些访问方式。

其中之一(饿汉式)代码体现:

              class Single{
			private Single() {  }  //私有化构造函数,避免创建对象
			private static Single  s=new Single();//自定义一个本类对象
			public Single getInstance(){   //用于外界访问自定义对象
				return s;
			}
		}	
		class SingleDemo {
			public static void main(String[] args) {
				Single s=Single.getInstance();
			}
		}
	Class SingleDemo  {
			Public static void main(String[] args) {
				Student s1=Student.getStudent();
				Student s2=Student.getStudent();
				s1.setAge(40)
				s2.setAge(50);
			}
		}
		Class Student  {
			private int age;
			private static Student s=new student();
			private Student() {}
			public static Student getStudent() {
				return s;
			}
			public void setAge(int age) {
				this.age=age;
			}
			public int getAge() {
				return age;
			}
		}
		内存分析如下:得出结果为50.
                 

首先类进入内存,将类中的方法加载进方法区中,此时Person类中还定义了一个Person类型的p并默认初始化为null,此时在堆内存中创建一个对象new Person 并对其age属性进行默认初始化值为0;并分配其内存地址值为 0x0045,并将此 地址值赋值给栈内存中的p1=0x0045,此时p1通过该地址值指向堆内存中的age.此时Person()加载进入栈内存,它里面有this 和age,this指向的当前调用该方法的对象p1.此时p1将指向堆内存中的地址值赋值给this.Person类方法通过该地址 值指 向堆内存中的实体。然后将5赋值给堆内存中的实体。此时堆内存中的age=5;然后Person方法弹栈。调用Person类的getInstance()方法加载进入栈内存,然后加地址值返回方法区中的p。此 时方法区中的Person指向堆内存中的实体。然 后弹栈。此时Person p1=Person.Instance();执行完毕,第二条语句同理。当执行完之后,p2=0x0045指向堆内存中的同一实体。P1调用Person类中的setAge的方法,对堆内存 中的实体进行赋值。此时age=40;s2调用Person类中的setAge 方法,对堆内存中的实体进行赋值。此时age=50.最后实体中的age的值为50。

模式二:懒汉式,代码体现如下:

	  class Single{

			private Single() {  }  
			private static Single  s=null;
			public Single getInstance(){   
				if(s==null) 
					s=new Single();				
				return s;
			}
		}	
		class SingleDemo {
			public static void main(String[] args) {
				Single s=Single.getInstance();
			}
		}
	开发时,建议使用饿汉式,因为它安全。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值