Java 面向对象,封装,继承

 1相关概念的理解

1.1面向过程、面向对象

面向过程与面向对象都是编程中,编写程序的一种思维方式。

面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程。(职员思想)

面向对象的程序设计方式,是遇到一件事时,思考“我该让谁来做”,然后那个“谁”就是对象,他要怎么做这件事是他自己的事,反正最后一群对象合力能把事就好就行了。(领导思想)

 

1.2面向对象思维方式的好处

面向对象思维方式是一种更符合人们思考习惯的思想

面向过程思维方式中更多的体现的是执行者(自己做事情),面向对象中更多的体现是指挥者(指挥对象做事情)。

面向对象思维方式将复杂的问题简单化。

 

2类与对象

2.1定义类

事物其实就是由特点(属性)和行为(功能)组成的。

通过计算机语言Java来描述这个事物,就是定义类,

定义类的格式:

public class 类名 {

//可编写0至n个属性

    数据类型 变量名1;

    数据类型 变量名2;

 

//可编写0至n个方法

修饰符 返回值类型 方法名(参数){

执行语句;

}

}

Tips:自定义类中:有main方法,其他方法就要加static,没有main,就不用加。

例: 

public class Car {
	String color;//颜色
	int tyre;//轮胎个数
	
	//功能:跑
	public void run(){
		System.out.println("颜色为"+color+",轮胎个数为"+tyre+"的小汽车在跑");
	}
}
public class Test {
	public static void main(String[] args) {
		Car c=new Car();
		c.color="红色";
		c.tyre=4;
		c.run();
	}
}

2.2成员变量和成员方法

类的真正意义就是在描述事物。属性和功能统称为事物中的成员。

事物的成员分为两种:成员属性和成员功能。

成员属性在代码中的体现就是成员变量

成员功能在代码中的体现就是成员方法

2.3类和对象的区别

类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。 

举例:

类是模型

对象是实体

设计时,是先有实体,再抽象出模型。

实际生产时,是先有模型,再有实体。

实际编程时,也是如此。

2.4局部变量和成员变量区别

1)定义的位置不同

成员变量定义在类中

局部变量定义在方法中或块(大扩号)中

例:

public class Student {
	String name;  //成员变量
	int age; //成员变量
	String sex; //成员变量
	
	public void study(String name){ //局部变量
		int book=0; //局部变量
		System.out.println("这个学生姓名为"+name+",年龄为"+age+",性别为"+sex); //这个name就成了局部变量,就近原则
		System.out.println("这个学生读了"+book+"本书");
	}
}

2)在内存中的位置不同

成员变量存储在堆内存的对象中

局部变量存储在栈内存的方法中

3)生命周期不同

成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失

局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失

4)初始化不同

成员变量因为在堆内存中,所有默认的初始化值

局部变量没有默认的初始化值,必须手动的给其赋值才可以使用

2.5基本类型和引用类型作为参数传递

例:

public class Test2 {
	public static void main(String[] args) {
		int a=1;
		double b=2;
		method1(a,b);
		System.out.println(a);
		System.out.println(b);
	}
	public static void method1(int a,double b){
		a=20;
		b=30;
	}
}

 

public class Test3 {
	public static void main(String[] args) {
		Student s=new Student();
		s.name="同学1";
		s.age=38;
		s.sex="男";
		method1(s);
		s.study();
	}
	public static void method1(Student s){
		s.name="同学2";
		s.age=18;
		s.sex="男";
	}
}

当引用变量作为参数传递时,这时其实是将引用变量空间中的内存地址(引用)复制了一份传递给了method1方法的s引用变量。这时会有两个引用同时指向堆中的同一个对象。当执行method1方法中的s.name="同学2"时,会根据s所持有的引用找到堆中的对象,并将其s属性的值改为同学2,method1方法弹栈。

由于是两个引用指向同一个对象,不管是哪一个引用改变了引用的所指向的对象的中的值,其他引用再次使用都是改变后的值。

3封装

面向对象三特征:封装,继承,多态 

封装的概念:隐藏了实现细节,还要对外提供可以访问的方式

3.1封装表现

1)方法就是一个最基本封装体。

2)类也是一个封装体。

 

3.2封装的好处

1)提高了代码的复用性。

2)隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。这是核心之一,也可以理解为就是封装的概念。

3)提高了安全性。

 

封装举例:机箱

3.3私有private

举例:定义一个Person类

Public class Person {
	String name;
	int age;
} 
public class Test {
	public static void main(String[] args) {
		Person p1=new Person();
		p1.name="小红帽";
		p1.age=-100; //不安全因素
		System.out.println(p1.name);
		System.out.println(p1.age);
	}
}

通过上述代码发现,虽然用Java代码把Person描述清楚了,但有个严重的问题,就是Person中的属性的行为可以任意访问和使用。这明显不符合实际需求(如代码中年龄为负值)。

解决办法:需要使用一个Java中的关键字也是一个修饰符 private(私有,权限修饰符)。只要将Person的属性和行为私有起来,这样就无法直接访问:

public class Person {
	private String name;
	private int age;
}

这时,Test类中访问不到了:

  

然后在Person类中提供对外访问接口:

public class Person {
	private String name;
	private int age;
	
	//赋值方法
	public void setName(String n){
		name=n;
	}	
	public void setAge(int a){
		if(a>=0&&a<=200){
			age=a;
		}else{
			age=0;
		}
	}
	
	//取值方法
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}		
}

在Test中: 

public class Test {
	public static void main(String[] args) {
		Person p1=new Person();
		
		p1.setName("小红帽");
		p1.setAge(-100);
		
		System.out.println(p1.getName());
		System.out.println(p1.getAge());
		
	}
}

总结:

类中不需要对外提供的内容都私有化,包括属性和方法。

以后再描述事物,属性都私有化,并提供setXxx,getXxx方法对其进行访问。

注意:私有仅仅是封装的体现形式而已。

在eclipse中有可以自动添加这两个方法的功能:

建好成员变量(并私有)后,在代码区右键-- Source-- Generate Getters and Setters

  

选择上变量,就会自动建好了:

3.4 this关键字

3.4.1成员变量和局部变量同名问题

  可以在成员变量名前面加上this.来区别成员变量和局部变量。

3.2.2 this代表本类对象

  具体代表哪个对象:

  哪个对象调用了this所在的方法,this就代表哪个对象。

例:比较年龄

public class Person {
	private String name;
	private int age;
	
	//赋值方法
	public void setName(String n){
		name=n;
	}	
	public void setAge(int a){
		if(a>=0&&a<=200){
			age=a;
		}else{
			age=0;
		}
	}
	
	//取值方法
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}	
	
	//判断是否同龄人
	public boolean compare(Person p){ //传入一个对象
		return this.age==p.age;
	}	
}
public class CompareAge {
	public static void main(String[] args) {
		Person p1=new Person();
		p1.setName("张");
		p1.setAge(18);
		
		Person p2=new Person();
		p2.setName("赵");
		p2.setAge(18);
		
		boolean flag=p1.compare(p2); 
		System.out.println(flag);	
		
	}
}

3.4.3内存解释(图稍后再放)

4 继承

继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。

Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。

4.1继承的格式和使用

class 子类 extends 父类 {}

先有父类,再有子类

分析时,是先有子类,再抽象出父类

例:

//员工(父类)
public class Emp {
	String name;
	int age;	
	public void work(){
		System.out.println(name+"员工正在工作");
	}
}
//研发部员工继承自员工
public class Rcenter extends Emp {

}
//维护部员工继承自员工
public class Mcenter extends Emp{
	//子类独有方法
	public void speak(){
		System.out.println("我叫"+name);
	}
}
//测试
public class Test {
	public static void main(String[] args) {
		Rcenter r=new Rcenter();
		r.name="小猪";
		r.age=18;
		System.out.println(r.name);
		System.out.println(r.age);
		r.work();
		
		Mcenter m=new Mcenter();
		m.name="小狗";
		m.age=17;
		m.work();
		m.speak();		
	}
}

4.2继承的好处

1)继承的出现提高了代码的复用性,提高软件开发效率。

2)继承的出现让类与类之间产生了关系,提供了多态的前提。

4.3继承中注意事项

1)类只支持单继承,不允许多继承。也就是说一个类只能有一个直接父类(人只能有一个亲生父亲)

  class A{}

  class B{}

  class C extends A,B{}  // 错误:C类不可以同时继承A类和B类

2)多个类可以继承一个父类(父亲可以有多个儿子)

  class A{}

  class B extends A{}

  class C extends A{}   // 类B和类C都可以继承类A

3)多层继承是可以的,即一个类的父类可以再去继承另外的父类(祖父,父,儿子)

  class A{}

  class B extends A{}   // 类B继承类A,类B是类A的子类

  class C extends B{}   // 类C继承类B,类C是类B的子类,同时也是类A的子类

4)子类和父类是一种相对概念。一个类是某个类父类的同时,也可以是另一个类的子类。

4.4成员变量、成员方法的变化

1)如果子类父类中出现不同名的成员变量,这时的访问是没有任何问题

2)父类中的成员变量是非私有的,子类中可以直接访问,若父类中的成员变量私有了,子类是不能直接访问的

3)当父类和子类中有相同的成员变量时,自己有,用自己的,自己没有,用父类的。(就近原则)

4)当子父类中出现了同名成员变量时,在子类中若要访问父类中的成员变量,必须使用关键字super来完成。super用来表示当前对象中包含的父类对象空间的引用。

Super表示父类对象super只能子类用)

格式:super.父类中的成员变量

例:

public class Fu {
	int a=1;	
}
public class Zi extends Fu{	
	int a=2;
	public void method(){
		int a=3;
		System.out.println("a="+a);
		System.out.println("a="+this.a);
		System.out.println("a="+super.a);
	}
}
public class Test {
	public static void main(String[] args) {
		Zi z=new Zi();
		System.out.println("a="+z.a);
		z.method();
	}
}

 

5)若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

4.5方法重写(覆盖)

4.5.1概念

子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖。

例:

public class Fu {
	public void show(){
		System.out.println("这是父类方法");
	}
}
public class Zi extends Fu{
	//方法重写
	public void show(){
		System.out.println("这是子类方法");
	}
} 
public class Test {
	public static void main(String[] args) {
		Zi z=new Zi();
		z.show();		
	}	
}

4.5.2方法重写(覆盖)的应用

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

在子类中,访问父类中的成员方法格式:

super.父类中的成员方法();

例:

public class Phone {
	public void show(){
		System.out.println("显示电话号码");
	}
	
	public void sendM(){
		System.out.println("发短信");
	}
	
	public void call(){
		System.out.println("打电话");
	}	
} 
public class Iphone extends Phone{
	public void show(){
		super.show(); //父类方法
		System.out.println("显示姓名");
		System.out.println("显示头像");
	}
}
public class Test {
	public static void main(String[] args) {
		Iphone i=new Iphone();
		i.show();
		i.sendM();
		i.call();
	}
}

4.5.3方法重写注意事项

1)子类方法覆盖父类方法,必须要保证权限大于等于父类权限(修饰符 default或不写小于public,以后会再学)。

class Fu(){	
    void show(){}
    public void method(){}
}
class Zi extends Fu{
    public void show(){}  //编译运行没问题
    void method(){}      //编译错误
}

2)写法上注意:必须一模一样:方法的返回值类型 方法名 参数列表都要一样

3)必须有父类,才有方法重写的概念

对比记忆:方法重载:在同一个类中

练习1:

项目经理类

属性:姓名 工号 工资 奖金

行为:工作work(打印姓名、工号、工资、奖金)

程序员类

属性:姓名 工号 工资

行为:工作work(打印姓名、工号、工资)

练习2:

已知学生类和老师类如下:

属性:姓名,年龄

行为:吃饭

老师有特有的方法:讲课

学生有特有的方法:学习

练习3:

已知猫类和狗类:

属性:毛的颜色,腿的个数

行为:吃饭

猫特有行为:抓老鼠catchMouse

狗特有行为:看家lookHome

猜你喜欢

转载自www.cnblogs.com/hzhjxx/p/10035315.html