java面向对象

什么是面向对象? 
面向对象是相对于面向过程而言的。 
无论过程还是对象都是生活中的一种思考方式。 



面向过程:注重的是执行的过程,强调的是执行的动作。 
C语言就是面向过程的语言,实现这个需求,其实就是定义三个功能(函数); 

面向对象:注重的是具体的事物,将具体的功能定义到该事物当中。 
     以后不用再定义具体功能,只要找到该事物,就已经具备了 
     这些功能。这个事物称为对象。 
   
总结面向对象: 
面向对象是一种符合现在人们思考习惯的一种的思想。 
面向对象出现让角色做着转变,从执行到了指挥者。 
面向对象将复杂的事情简单化。 

不强调过程,而是强调对象,找到对象,其实就是找到了这些功能。 

面向对象其实就是基于面向过程而来。 

完成需求时: 
先去找具有所需的功能的对象来用。 
如果该对象不存在,那么创建一个具有所需功能的对象。 
这样简化开发并提高复用。 

面向对象的开发:不断地创建对象,使用对象,并维护对象和对象之间的关系。 

——————————————————————————————————————— 

面向对象的三个特征: 
封装,继承,多态 
——————————————————————————————————————— 
类与对象的关系? 
类就是对现实事物的描述,就是一组对象的 
共性属性和行为的抽象。 
而对象就是该类事物具体实实在在的个体。 


如何创建对象? 
类名 对象名 = new 类名(); 

Car car = new Car(); 
这里的Car是类名,而car是类类型变量。 
类类型变量指定指向对象。 

——————————————————————————————————————— 

什么是成员变量,什么是局部变量? 
定义在类中的变量就是成员变量,定义在函数的变量就是局部变量。 

成员变量与局部变量的区别? 
作用范围: 
成员变量:(实例变量)定义在类中,作用于整个类。 
局部变量:只能在它所属的局部大括号中有效 
存储情况: 
成员变量:存储在堆内存中,随着对象的存在而存在。 
    当对象变成垃圾被回收时,该对象中的成员变量 
    也就随之消失 
  局部变量:存储在栈内存中,当方法被调用,或者语句被执 
  行的时候,才存在,当方法执行完毕,或者语句 
    运行完毕时,局部变量会被自动释放。 
初始化情况: 
成员变量:在内存中有默认初始化值。 
局部变量:必须手动初始化。 
   
   
class Demo{ 
  int num; 
  public void show(){ 
  int x = 4; 
  } 


num就是成员变量,x就是局部变量。 


当在一个方法中,局部变量与成员变量重名,会先使用局部变量。 
class Demo{ 
  int num = 100; 
  public void show(){ 
  int num = 4; 
  System.out.println(num); 
  } 

运行结果是4; 


——————————————————————————————————————— 


什么是匿名对象? 
没有名字的对象,是定义对象的一种简化形式。 
当对象对方法进行一次调用的时候,可以使用匿名对象对代码进行简化 



Car c = new Car(); 
c.run();只是非匿名对象 

new Car().run();匿名对象 


什么是封装(Encapsulation)? 
是指隐藏对象的属性和实现细节,仅仅对外提供公共访问方式。 


封装的好处: 
将变化隔离 
便于使用 
提高重用性 
提高安全性 

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

private 是权限修饰符,只能修饰成员(成员变量和成员函数) 
私有的成员只在本类中有效。 

当成员私有后,提高了安全性。但访问权限降低了。 
可以通过对外提供公有方法的形式对其进行访问。 

私有就是封装的一种体现而已。 


构造函数的定义: 
class Person{ 
  Person(){ 
  System.out.println(“person run”); 
  } 


——————————————————————————————————————— 

构造函数与普通函数的区别: 
构造函数在对象建立时就被直接调用,用于给对象进行初始化。 
一般函数用于定义对象应该具备的功能,而构造函数是在创建对象时,应具备的初始化的内容 
构造函数是在对象建立时被调用。给对象初始化。 
一般函数是在对象建立后,当对象调用该功能时才会执行。 


当类中没有定义构造函数时,系统会指定给该类加上一个空参数的构造函数。这个 
是类中默认的构造函数,当类中如果自定义了构造函数,这是默认构造函数就没有了。 

在一个类中可以有多个构造函数,进行不同的初始化。 



构造函数的特点: 
函数名与类名相同 
不用定义返回值类型 
没有具体的返回值 


构造函数的作用? 
给对象进行初始化 

**默认构造函数的特点。 
多个构造函数以重载的形式存在。 

——————————————————————————————————————— 

关键字this: 
当局部变量和成员变量重名时,为了以示区分。 
可以用一个关键字this来完成。 

this:关键字代表是对象的引用。也就是this在指向一个对象。 

this:就代表所在函数所属对象的引用。哪个对象调用this所在的函数, 
this就代表哪个对象。 


类中的非静态方法都需要被对象所调用, 
所以每一个方法都有自己所属的对象,都用this表示。 



对象的建立以及初始化过程: 
Person p = new Person(); 
将person.class文件加载进内存。 
如果p定义在函数中,那么在栈内存中开辟一个变量空间p 
在堆内存中给对象分配空间 
给对象中的属性进行默认初始化 
给对象中的属性进行显示初始化 
调用构造代码块对对象进行初始化。(执行类中的构造代码块) 
调用对应的构造函数进行对象初始化。(对象初始化完毕) 
将对象内存地址赋值给p变量。让p变量指向对象 



关键字static: 
static是一个修饰符,用于修饰成员(成员变量和成员函数) 
1.静态成员随着类的加载而加载,不是随着对象而产生。 
2.静态成员优先于对象存在。 
3.静态成员被所有对象共享 
4.静态成员多了一个调用方式,类名点的方式调用。 

静态使用注意事项: 
1.静态方法只能访问静态成员。 
2.非静态方法可以访问静态数据。 
3.静态方法中不可以定义this,super关键字(因为this代表是对象,而静态存在时,有可能没有对象,this没有任何对象代表) 
4.主函数是静态的。 

静态好处与弊端? 
好处:静态成员多了一种调用方式,可以直接被类名调用,也可以被对象调用 
弊端:静态方法只能访问静态成员,出现了访问局限性 

静态修饰的数据是对象共享的数据,非静态数据是每一个对象特有的数据。 

当成员变量被静态修饰后,和非静态成员变量的区别? 
1.静态变量也称为类变量,也就是直接可以被类名调用的,这个变量是属于类的。 
非静态变量称为成员变量,或者实例变量,是被对象调用的。 
2.静态变量随着类的加载而加载,也以为这随着类的消失而消失,生命周期最长。 
实例变量,随着对象的创建而加载,随着对象的消失而消失 
3.静态变量存储在方法区的静态区中。实例变量存在于对象所属的堆内存中。 
4.静态变量数据,被所有对象所共享。实例变量是对象中的特有数据 



什么时候使用static? 
成员变量: 
  什么时候被静态修饰呢? 
  当该成员变量所存储的数据,每一个对象都一样时,这时没有必要把该数据存储到每一个对象中,只要让所有对象共享该数据即可 
   
  当数据需要被对象共享时,就用static修饰。 
   
成员函数: 
  当成员函数内并没有访问对象中的特有数据时,就将该方法定义成静态的。 
   
  该函数如果访问了成员变量,该函数就是非静态的。 
  该函数没有访问过成员变量,或者访问过静态的成员变量,为了程序的严谨性,将该方法定义成静态的,因为该方法不需要对象也可以被调用。 

——————————————————————————————————————— 


继承(extends):子类拥有父类的属性和方法。 

继承的出现,让类与类之间产生了关系。而这个关系出现,就导致了面向对象的第三个特征,继承就是多态的前提。 

Java中只支持单继承,不支持多继承(java将多继承进行改良,提高安全性); 

Java中可以存在多层(多重)继承。 
class A{} 
class B extends a{} 
class c extends b{} 
这是一个继承体系。 
A类中定义是这个体系中的最共性的功能。 
要使用这个体系的功能,建议建立最子类的对象来完成调用。 


父类的由来都是子类不断向上抽取而来的。就代表着,A中定义的功能是该体系中最共性的功能。所以要了解这个体系的功能,只要参考A类中的功能即可。所以建议建立c对象,因为c中可以使用a类中的功能,也可以使用c类中的特有功能。 


什么时候使用继承? 
继承是用于程序设计的。只要一个事物是另一个事物的一种,就可以用继承体现。 

怎么判断是另一个事物中的一种? 
那么可以先视为可以继承,用更简单的方式判断,一个类如果继承了另一个类,那么 
这个类是否应该具备另一个类中的所有成员,如果可以,继承有效,如果不可以,那么 
无法继承。 

继承的好处: 
可以提高代码的复用性。有利于程序的扩展,不需要改动原来的代码的情况下,就可以实现程序的功能扩展。 

**不要为了获取另一个类中的部分功能而继承。这样是为了提高复用性而继承,并没有判断 
事物之间的关系,这样不可取。 


继承出现后,在子父类中成员的特点。 
  当子父类中出现同名的成员变量时,这时为了区分两个变量,在子类用this调用子类变量,用super调用的是父类的变量。 
  当子父类中出现一模一样的函数时,子类对象在调用该函数时,运行的是子类中的函数。 
  父类中的函数好像被覆盖一样。 
  这就是函数的另一个特性:覆盖(复写,重写)override 函数的另一个特性:重载overload 
  覆盖:在子父类中出现一模一样的函数,称为覆盖。 
   
   
   
  子父类中构造函数的特点: 
  class Fu{ 
  Fu(){ 
  System.out.println(“fu”); 
  } 
  } class Zi extends Fu(){ 
  Zi(){ 
  System.out.println(“zi”); 
  } 
  } 
  创建子类之后,运行结果是fu zi。 
  这是因为在子类的构造函数的第一行,其实就是一条默认的隐式语句 super(); 
  super():和this():用法是一样的,this():调用了本类中的构造函数。 
  super():调用了父类中的构造函数。 
  子类实例化的时候,因为子类继承父类的成员数据, 
  **所以必须要先看父类是如何对自己的成员初始化的。 
   子类的所有构造函数默认都会访问父类中空参数的构造函数。 
  当父类中没有定义空参数的构造时,子类必须通过super语句明确指定要访问的父类中的构造函数。(子类的构造函数无论如何都必须访问父类中的构造函数,要明确父类的初始化过程) 
   
  Super语句用于访问父类的初始化,而初始化动作要先完成,所以super语句必须定义在构造函数的第一行。 
  那么就和曾经的this语句冲突了,因为this语句也要定义在构造函数的第一行。 
  所以一个构造函数中,只能有一个要么this语句,要么super语句。 
  而且不冲突,因为子类中至少会有一个构造函数会去访问父类中的构造函数,一样可以完成父类初始化。 
  这个就是子类的实例化过程。 
   
   
  class Fu{ 
  Fu(int x){ 
  System.out.println(“fu .. ”+x); 
  }
  } 
  class Zi extends Fu{ 
  Zi(){ 
  this(20); 
  System.out.println(“zi ... ”+x); 
  } 
  Zi(int x){ 
  super(90); 
  System.out.println(“zi ... ”+x); 
  } 
  } 
  在创建子类的时候,如果调用无参的构造方法,会先访问子类中有参的构造方法,然后去访问父类的构造方法。 
   
   
  什么时候使用覆盖? 
  当子类的一些方法不同其他完全相同时,我们可以把与父类不同的方法覆盖掉。 
   
  super和this的用法很相似。但是 
  this代表是本类对象的引用,可以区分局部变量和成员变量重名。 
  super代表的是父类的存储空间,可以区分子父类变量重名。 
   
子类为什么可以访问父类中的成员? 
因为子类中有持有一个父类空间的标示super。在创建子类的时候,会先有父类的属性和方法。 

子类不可以直接访问父类中的私有成员,可以通过间接的形式访问。 

子父类中覆盖的一些细节: 
1.子类覆盖父类必须要保证权限大于等于父类 
2.静态覆盖静态(静态不能覆盖非静态,非静态也不能覆盖静态) 


继承的弊端: 
打破的封装性。 
如果恶意继承进行不正确的覆盖,会导致原功能的错误。打破了封装性。 

———————————————————————————————— 
关键字final: 
1.它可以修饰类,可以修饰变量 
2.final修饰的是一个最终类,不可以被继承。 
3.final修饰的方法不可以被覆盖。 
4.final修饰的变量是一个常量,只能被赋值一次。这个赋指的是显示初始化。 

什么时候将变量修饰成final? 
通常在程序中会使用一些不会变化的数据。比如3.14 
哪儿这个数据直接使用是可以的,但是不易阅读,所以可以起一个容易阅读的名称。 
final double PI = 3.14; 

Final修饰的常量定义一般都有规范书写,被final修饰的常量名称,所有字母都大写 
如果有多个单词,单词之间用下划线(_)连接,MY_NUMBER; 


———————————————————————————————— 

抽象: 
抽象就是不具体的。 

抽象类: 
两个类中有共性的功能,声明相同,但是具体内容不同,这时,我们只对相同的功能声明进行抽取,而不抽取功能的内容。 

**当类中出现了抽象的方法后,该类也必须变成抽象类。 

抽象类的特点: 
1.抽象类和方法必须用abstract关键字修饰。 
2.抽象方法一定要存放在抽象类中。 
3.抽象类不可以被实例化。也就是不可以通过该类建立对象。(因为抽象类建立对象后,调用抽象方法没意义) 
4.只有抽象类的子类将抽象类中的抽象方法全部覆盖,该子类就可以建立对象了 
如果只有部分覆盖,那么子类还是一个抽象类。 

抽象类什么时候定义: 
当对象具备的相同的功能,但是具体的实现细节不相同,这时就可以抽象一个类。 

**抽象类可以定义事物的共性内容,并且强迫子类去实现,否则子类还是抽象类。 

抽象类中的一些细节: 
1.抽象类中是否有构造函数 
有(只要是class定义的类,里面就有构造函数) 
抽象类中的构造函数用于给子类提供实例化 

2.抽象类中是否可以不定义抽象方法 
可以(没有抽象方法的抽象类存在的意义仅仅是不让该类创建对象,因为创建没有意义,在java awt中有体现) 

3.抽象关键字和哪些关键字不可以共存 
final :如果方法被抽象了,就需要被覆盖,而final是不可以被覆盖的。 
private :如果函数被私有了,子类无法直接访问,无法覆盖 
static:不需要对象,类名既可以调用方法,而调用抽象方法没有意义。 

—————————————————————————————————————— 

接口: 
当抽象类中的方法都是抽象的时候,这时候可以把该类定义成接口的形式。 
接口是特殊的抽象类。 
(java中的interface,java中的接口的体现。 
广义理解:只要对外提供规则都属于接口范畴) 
1.接口就是对外暴露的规则 
2.接口是功能的扩展 
3.接口的出现降低了耦合性(紧密联系程度); 

接口的特点: 
1.接口的方法都是抽象的。 
2.接口不可以被实例化。 
3.只有子类实现了接口中的所有抽象方法后,该子类才可以实例化,否则子类还是一个抽象类 

格式特点: 
当定义接口时,接口中的常见的成员有两种; 
1.全局常量。 
2.抽象方法。 
而且接口中的成员都有固定的修饰符: 
全局常量:public static final 
成员方法:public abstract 
这些修饰符不写,系统也会自动加上。 

接口中的成员都是public权限的。 

因为接口成员都是abstract,所以子类想要实例化,必须把全部方法都实现。 

如果B是一个接口,A去实现B用到关键字implements,而且子类的方法必须是public 
(因为接口中是方法都public) 

class A implements B{ 



继承和实现的区别? 
1.类与类之间称为继承:因为该类无论是抽象的还是非抽象的,它内部都可以定义非抽象方法,这个方法可以直接被子类使用,所以子类继承就可以使用了。 
类与接口是实现关系:因为接口中的方法都是抽象的,必须由子类实现才能实例化 
所以就用了更确切的关键字来表示:implements 
2.类只能单继承,接口可以多实现 

接口的好处: 
一个类可以实现多个接口。
一个类在继承另一个类的同时可以实现多个接口。 

接口和抽象类的区别: 
1.抽象类只能被单继承,接口可以多实现 
2.抽象类中可以定义非抽象方法,直接被子类使用。 
接口中只有抽象方法,必须被子类实现后才可以被使用。 
3.抽象类中定义体系中的基本共性功能。 
接口中通常定义体系中的扩展功能。 
4.接口的出现避免了单继承的局限性。 
5.抽象类被继承,是从属(is a)关系。 
接口可以被实现,是类似(like a)关系 

接口与接口之间也可以有继承关系,接口可以多继承。类不可以。 

—————————————————————————————————————— 

多态: 
某一类事物的多种存在形态。 

1. 在程序中的体现:(多态的实现机制) 
  父类引用或者接口引用指向了自己的子类对象。 
2. 好处: 
  提高了代码的扩展性。 
3. 前提: 
  1.类与类之间必须有继承关系或者实现关系。 
  2.通常都需要进行覆盖。 
4. 弊端: 
  进行多态应用时,前期并不知道后期会有多少个子类出现,但是可以使用父类的引用来调用父类的方法。而后期哪个子类对象出现就执行哪个子类的具体方法实现。 
这就是程序的扩展性。 
但是,前期调用的时候,只能调用父类中的方法,而不能调用具体子类的方法,因为前期还不知道具体的子类是谁。 

多态的应用思想: 
以前,定义对象,并指挥对象做事情(调用对象方法) 
当对象多了以后,指挥动作就会变得很麻烦。 
这时重新思考问题,找到这些对象的共性类型。 
直接指挥这个共性类型做事情即可,这样凡是属于这个类型的个体都会执行。 

Animal a = new Cat(); 
这个叫父类应用指向子类对象,子类对象提升为父类型,向上转型,自动类型提升 
想要使用cat的特有方法,只能进行强制转换 
Cat c = (Cat)a; 
c.eat(); 
c.catchMouse(); 

在转型过程中,其实都是子类对象在做着变化。 
当你想使用子类的特有功能时,必需将父类型转成子类型才可以使用。 
注意:必需保证,这个父类型指向的是该子类型的对象。 

绝对不要将父类对象转成子类类型。 

可以对传入的对象进行类型的判断。通过instanceof关键字完成。 
对象instanceof类型用于判断该对象是否所属于该类型。 

多用于接口类型的引用指向其子类对象。 

多态中的细节: 
  成员变量: 
  编译时期:看的引用型变量所属的类中是否有所调用的变量。 
  运行时期:也是看引用型变量所属的类是否有调用的变量。 
  简单的说:成员变量,编译和运行都看等号左边。 
   
  成员函数: 
  编译时期:看的引用型变量所属的类中是否有调用的方法。 
  运行时期:看的对象所属的类中是否有调用方法。 
  简单说:对于成员函数,编译看左,运行看右。 
   
   
  静态函数: 
  编译时期:看的是引用型变量所属的类中是否有调用的方法。 
  运行时期:也是看的是引用型变量所属的类中是否有调用的方法。 
  简单说:对于静态函数,编译看左边,运行也看左边。 
   
成员变量和静态成员:编译和运行都看左边。 
只有非静态的成员函数,编译看左边,运行看右边。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值