黑马程序员_面向对象(1) 多态&继承&封装&关键字

本文介绍了面向对象编程的基本概念,包括构造函数与继承的关系,如何通过super调用父类构造函数,以及多态、封装的重要性。此外,还详细讲解了this、super、static和final等关键字的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------- android培训 java培训 、期待与您交流! ----------

 一.面向对象概述

       何谓面向对象:
    所有的东西都是对象。
  程序是一大堆对象的集合,他们通过消息传递,各个对象之间知道要做些什么。
  每个对象都分配有自己的存储空间,可容纳其他对象。
  每个对象都有一个类型。
  同一类的所有对象能接收相同的消息
   
     对象特征:
     ehavior—说明这个对象能做什么。
   State—当对象施加方法时对象的反映。
   Identity---与其他相似行为对象的区分标志,每一个对象有唯一的indentity, 而这3者是相互影响的。
    最重要的思想就是类,类是模板是蓝图,从类中构造一个对象,即创建了一个类的实例,打个比方:类好比一个建材市场,其中许多子类--各种各样的装饰材  料,而我们自己装饰的房子就是自己选择需要的材料
     类之间的关系: 依赖关系(use - a),聚合关系(has - a),继承关系(is - a)
     OOP 设计最重要经验:谁拥有数据,谁就对外操作这些数据的方法
     面试题:两块石头磨成一把石刀,石刀可以砍树,砍成木材,木材做成椅子。
     木材做成椅子,木材是原材料,工厂设计     
chair = ChairFactory.makeChar(wood);
     木材是由石刀砍树得来了
wood = StoneKnife.cut(free)

            石刀又是有两块石头磨成而来了,石头是原材料,工厂设计
stoneKnife = KnifeFactory.makeKnife(stone);
          
          面向对象特征: 
      封装: 隐藏对象的属性和实现的细节,只提供公共访问的方式。比如电脑里面的配件普通人不需要知道里面是怎样连接的,只需要知道外面的接口怎样使用有什么功能即可!这样的好处就是提高了复用性,安全性,还可以将变化隔离在那一部分代码,方便使用
    eg:
  public void print(Object obj){
  System.out.println(obj);
}

      继承:
      多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只需要继承那个类即可

      多态: 一个对象在程序不同运行时刻代表的多种状态,父类或接口的引用指向子类
      
     
  成员变量与局部变量
  作用域:成员变量用于整个类
         局部变量用于方法和语句中
  生命周期:成员变量随着类的创建,存在堆区,随着类的消失而消失
           局部变量 随着方法调用或者语句执行而存放在栈内存,调用后或语句结束自动释放
  初始值: 成员变量有默认值
          局部变量必须赋值
  eg:
class  Test{
   int a; // 成员变量
   public void methA(){
      int b = 0; // 局部变量
   }
}

  匿名对象: 没有名字的对象,调用一次,被gc自动释放回收
  eg:   
new Random().nextInt(100);
 
  构造方法
  特点: 方法名与类名相同,无返回值,无返回值类型
  作用: 构造函数是用于创建对象并对其进行初始化赋值,对象一旦创建就会调用相应的构造函数
    注意:没有定义构造方法,系统默认缺省的无参构造方法
    eg:
public class Test{
     Test(){ //无参构造
   
     }
     Test(int a,int b){ // 有参构造
     }
 }

构造函数没有覆盖。

构造函数没有继承过来,通过super访问父类构造函数。

在子类的构造函数中第一行有一个默认的隐式语句。super();

子类实例化过程,子类中所有的构造函数默认都会访问父类中的空参数的构造函数

 eg: 

class Fu 
{
	private int num = 4;
	public void setNum(int num)
	{
		this.num =num;
	}
	public int getNum()
	{
		return this.num;
	}
}

class Zi extends Fu
{
	//int num = 5;
	void show()
	{
		System.out.println(num);
	}
}

class  ExtendsDemo2
{
	public static void main(String[] args) 
	{
		Zi z = new Zi();
		z.show();
		//System.out.println(z.num+"...."+z.num);
	}
}


  对象在JVM初始化过程
  
/**一个对象实例化过程:
Person p = new Person();
1.jvm读取并解释的Person.class文件,进行解析,并加载进内存,进入到方法区,形成常量池与方法表
2.并会先加载Person的父类(如果有直接的父类的情况下).在堆内存中开辟空间,分配地址。
3.并在对象空间中,对对象中的属性进行默认初始化。
4.调用对应的构造函数进行初始化。
5.在构造函数中,第一行会先调用父类中的构造函数进行初始化。
6.父类初始化完毕后,再对子类的属性进行显示初始化。
7.在进行子类构造函数的特定初始化。
8.初始化完毕后,将地址值赋值给引用变量。 
**/
class Fu{
	int num = 4;
	void show1(){
	System.out.println("fu show run");
	}
}

class Zi extends Fu{
	int num = 5;
	void show(){
	System.out.println(num+"......"+super.num); 
	} 
	void show1(){
	System.out.println("zi show run");
	}
}

public class ExtendDemo2 { 
	public static void main(String[] args) {

	Zi z = new Zi();
	z.show();
	z.show1();
	//z.show2();
	}
}

 内存图表现形式:
 
 -------------------------------------------------------------------------------------------------------------------------

 二.多态与继承特性

 一个类方法重写,多个类继承关系方法覆写,体现多态性质
 某一种事物存在的多种体现形态。 
多态自始至终都是子类对象在做着变化。 
多态的体现: 
1.父类的引用指向子类的对象(子类对象类型提升,自动向上转型) 
2.父类的引用页可以接受自己的子类对象,(向下转型,需要强制类型转换) 
多态的前提:必须是类与类之间有关系,要么继承,要么实现。 
多态的好处: 
1.多态大大提高了程序的扩展性 
2.通常还有一个问题在覆盖 
eg:多态判断
class Animal
{
}

class Cat extends Animal
{
}

class Test
{
	Animal animal = new Cat();//子类对象类型提升,自动向上转型
	Cat cat = (Cat)animal;//父类引用转换为子类类型,向下转型需要强制类型转换
}
eg:多态体现
abstract class Animal{

	abstract void eat();

}

class Dog extends Animal{

	void eat(){

		System.out.println("啃骨头");

	}

	void lookHome(){

		System.out.println("看家");

	}

}

class Cat extends Animal{

	void eat(){

		System.out.println("吃鱼"); 

	}

	void catchMouse(){

		System.out.println("抓老鼠");

	}

}


public class DuoTaiDemo {

	public static void main(String[] args){

		Animal a = new Cat();对象共性,都是动物

		method(a);

		method(new Dog());

	}


	public static void method(Animal a){

		a.eat();

	}

}

java保留了这种机制用另一种体现形式来完成表示多实现。 
java支持多层继承,通过接口实现,也就是继承体系。 
父类与子类中变量关系 
子类继承父类后会拥有父类的成员,只不过有些成员不可见。 
加载顺序:先加载父类成员后加载子类成员。 
子父类中的变量: 
如果子类中出现非私有的同名成员变量时,子类要访问本来变量用this,访问父类中的同名变量用super。 

父类与子类中函数 
当子类中出现和父类一模一样的函数(参数列表,返回值)时,当子类对象调用该函数,会运行子类函数的内容,如同父类被覆盖一样。这种情况是函数的另一种特性,重写(覆盖)。 
覆盖: 
1.子类覆盖父类,必须保证子类方法权限大于等于父类方法权限,才可以覆盖,否则编译失 败。 
2.静态只能覆盖静态。因为静态优先于对象存在。 
3.如果子类方法与父类私有方法同名,无法重写但不会报错,是一个新方法。 
重载 
当一个类中出现方法名相同,参数列表不同的方法时,被称为重载。重载可以改变返回值,因为它只看参数列表和名称。
 

 -------------------------------------------------------------------------------------------------------------------------

 三.封装特性 

        隐藏实现细节,并对外提供公共的访问方式。
函数或者类都是一个封装体。
特点:
1,隔离的变量。
2,便于使用。
3,提高复用。

      私有在源代码中的使用就是在本类中有效。
      通常会将成员变量xxx私有化,并对外提供对应的setXxx getXxx方法对其进行访问。
      其实目的就是成员变量访问进行控制。 让成员的访问具备可控性,提高了程序的健壮性。
      私有仅仅是封装的体现形式之一而已
      eg:      
public class Test{
 private int a,int b;
 public int getA(){
   return this.a;
 }
public void setA(int a){
   this.a = a;
 }
}

-------------------------------------------------------------------------------------------------------------------------

 四.关键字(this,super,static,final)

        this:代表的是对象。哪个对象调用了this所在的函数,this就代表哪个对象。 
用法体现
1,当成员变量和局部变量同名时,可以用this区别。
2,当构造函数中调用本类其他构造函数时,可以用this完成。 this(实际参数);
     这种调用必须定义在构造函数的第一行。初始化动作先完成。
应用:只要在定义功能时,用到了本类对象,那么就使用this来表示。

       static关键字:
特点:
1,修饰成员。,
2,随着类加载,随着类消失。
3,优先于对象。
4,用类名直接访问 
使用注意事项:
1,静态方法只能访问静态,静态有访问局限性。
2,静态方法中不能有this super关键字。
3,主函数是静态的
        什么时候使用静态?
1,当成员变量的数据各个对象都相同时,可以用static修饰,让多个对象共享。
2,函数如果访问了特有数据(非静态成员变量),该函数是非静态的。
     函数如果没有访问特有数据,那么该函数就可以静态修饰
final 关键字
/*
final : 最终。作为一个修饰符,
1,可以修饰类,函数,变量。
2,被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3,被final修饰的方法不可以被复写。
4,被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,有可以修饰局部变量。
	当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。
	而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成。
	单词间通过_连接。
5,内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。

*/

class Demo
{
	final int x = 3;
	public static final double PI = 3.14;
	final void show1()
	{}
	void show2()
	{
		final int y = 4;
		System.out.println(3.14);
	}
}
class SubDemo extends Demo
{
	//void show1(){}
}
class FinalDemo 
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}


 代码块:
         1,局部代码快。
对局部变量的生命周期进行控制。
             eg:
public void load(){
 {
    int i = 0,y =0;
    }
}


2,构造代码块。
     对所有对象进行初始化。                 
         eg:
public class Test{
  
   {
    
       }
 public void methodA(){
 
 }
 public void methodB(){

 }
}

3,静态代码块。
对类进行初始化
       
/*
静态代码块。
格式:
static
{
	静态代码块中的执行语句。
}

特点:随着类的加载而执行,只执行一次,并优先于主函数。
用于给类进行初始化的。

*/

class StaticCode
{
	int num = 9;
	StaticCode()
	{
		System.out.println("b");
	}

	static
	{
		System.out.println("a");
	}
	{
		System.out.println("c"+this.num);
	}

	StaticCode(int x)
	{
		System.out.println("d");
	}
	public static void show()
	{
		System.out.println("show run");
	}
}

class StaticCodeDemo 
{
	static
	{
		//System.out.println("b");
	}
	public static void main(String[] args) 
	{
		new StaticCode(4);//a c d 
		//new StaticCode();
		//new StaticCode();
		//System.out.println("over");
		//StaticCode.show();
		//StaticCode s = null;
		//s = new StaticCode();

		//StaticCode.show();


	}
	static
	{
		///System.out.println("c");
	}
}


-------android培训java培训、期待与您交流! ----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值