java基础之面向对象(1)

时间:2023-02-15 14:42:14

面向对象思想引入

前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。

面向过程思想概述

我们来回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。

在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。

那么什么是面向过程开发呢面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。

面向过程的代表语言:C语言

面向对象思想概述

当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。接下来我们看看面向对象到底是什么?

面向对象思想特点

是一种更符合我们思想习惯的思想

可以将复杂的事情简单化

将我们从执行者变成了指挥者

角色发生了转换

面向对象特征

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

类与对象关系

类:是一组相关的属性和行为的集合

对象:是该类事物的具体体现

举例:

类 学生

对象 班长就是一个对象

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

在类中的位置不同

成员变量 类中方法外

局部变量 方法内或者方法声明上

在内存中的位置不同

成员变量 堆内存

局部变量 栈内存

生命周期不同

成员变量 随着对象的存在而存在,随着对象的消失而消失

局部变量 随着方法的调用而存在,随着方法的调用完毕而消失

初始化值不同

成员变量 有默认的初始化值

局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

匿名对象

匿名对象:就是没有名字的对象。

是对象的一种简化表示形式

匿名对象的两种使用情况

对象调用方法仅仅一次的时候

作为实际参数传递

 

void show(  Person p ){}
Person p  = new Person();

show( p );             

show(  new Person()   )

封装概述

是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

隐藏实现细节,提供公共的访问方式

提高了代码的复用性

提高安全性。

封装原则:

将不需要对外提供的内容都隐藏起来。

把属性隐藏,提供公共方法对其访问。

private关键字:

是一个权限修饰符。

可以修饰成员(成员变量和成员方法)

private修饰的成员只在本类中才能访问。

 

private最常见的应用:

把成员变量用private修饰

提供对应的getXxx()/setXxx()方法

class Student  {

private String name;

private int age;

public void setName(String name){

 this.name=name;

}

public String  getName(){

return name;

}

public void setAge(int age){

    this.age=age;

}

public int getAge(){

 return age;

}

 

}

class Test1 {

public static void main(String[] args) {

Student s=new Student();

s.setName("张三");

System.out.println(s.getName());

s.setAge(20);

System.out.println(s.getAge());

}

}

this关键字

this:代表所在类的对象引用

记住:

方法被哪个对象调用,this就代表那个对象

什么时候使用this?

局部变量隐藏成员变量

构造方法作用概述

给对象的数据进行初始化

构造方法格式

方法名与类名相同

没有返回值类型,连void都没有

没有具体的返回值

构造方法注意事项

如果你不提供构造方法,系统会给出默认构造方法

如果你提供了构造方法,系统将不再提供

构造方法也是可以重载的

类的成员方法

方法具体划分:

根据返回值

有明确返回值方法

返回void类型的方法

根据形式参数

无参方法

带参方法

一个基本类的标准代码写法

成员变量private

构造方法

无参构造方法

带参构造方法

成员方法

getXxx()

setXxx()

给成员变量赋值的方式

无参构造方法+setXxx()

带参构造方法

类的初始化过程

Student s = new Student();在内存中做了哪些事情?  private String name="张三";

加载Student.class文件进内存

在栈内存为s开辟空间

在堆内存为学生对象开辟空间

对学生对象的成员变量进行默认初始化

对学生对象的成员变量进行显示初始化

通过构造方法对学生对象的成员变量赋值

学生对象初始化完毕,把对象地址赋值给s变量

static关键字

可以修饰成员变量和成员方法

static关键字特点

随着类的加载而加载

优先于对象存在

被类的所有对象共享

这也是我们判断是否使用静态关键字的条件

可以通过类名调用

static关键字注意事项

在静态方法中是没有this关键字的

静态方法只能访问静态的成员变量和静态的成员方法

 代码块

Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)

局部代码块 

在方法中出现;限定变量生命周期,及早释放,提高内存利用率

构造代码块 

在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行

静态代码块 在类中方法外出现,加了static修饰

在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行一次。

 

class Demo {

//静态代码块

static {

System.out.println("我是静态代码块");

}

//构造代码块

{

int j = 5;

System.out.println("j="+j);

}

public Demo(){

System.out.println("空参数构造方法");

}

 

//构造代码块

{

int k = 25;

System.out.println("k="+k);

}

}

 

class CodeBlockDemo {

public static void main(String[] args) {

//局部代码块

{

int i = 5;

//System.out.println("i=" + i);

}

//System.out.println("i --- "+i);

 

//---------------------------

new Demo();

System.out.println("----------------");

new Demo();

System.out.println("----------------");

new Demo();

}

}

静态代码块与 构造代码块 与 构造方法 的执行顺序?

静态代码块 -->构造代码块 -->  构造方法

class Demo {

//静态代码块

static {

System.out.println("aaa");

}

 

//构造代码块

{

System.out.println("bbb");

}

 

//构造方法

public Demo(){

System.out.println("ccc");

}

 

//构造代码块

{

System.out.println("ddd"); 

}

 

//静态代码块

static {

System.out.println("eee");

}

}

 

class CodeBlockTest {

 

//静态代码块

static {

System.out.println("000");

}

 

public static void main(String[] args) {

new Demo();

System.out.println("---------");

new Demo();

System.out.println("---------");

new Demo();

System.out.println("---------");

}

}

 

结果为000

aaa

eee

bbb

ddd

ccc

继承概述

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

通过extends关键字可以实现类与类的继承

class 子类名 extends 父类名 {}   Object

单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。

有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。

如:

class Student {

private String name;

private int age;

 

public Student(){}

public Student(String name, int age){

this.name = name;

this.age = age;

}

 

//setXxx() getXxx()

}

 

class Teacher {

private String name;

private int age;

 

public Teacher(){}

public Teacher(String name, int age){

this.name = name;

this.age = age;

}

 

//setXxx()  getXxx()

}

 

发现上面书写的代码,代码重复量太多,可以把相同的代码 抽取出来,放到单独的一个类中,然后让其他的类 与 这个单独类的产生关系

使用继承:

 

class Person {

private String name;

private int age;

 

public Person(){}

public Person(String name, int age){

this.name = name;

this.age = age;

}

//setXxx() getXxx()

}

class Student extends Person {}

class Teacher extends Person {}

class ExtendsDemo {

public static void main(String[] args) {

System.out.println("Hello World!");

}

}

继承的好处

提高了代码的复用性

多个类相同的成员可以放到同一个类中

提高了代码的维护性

如果功能的代码需要修改,修改一处即可

让类与类之间产生了关系,是多态的前提

其实这也是继承的一个弊端:类的耦合性很强

Java中继承的注意事项

子类只能继承父类所有非私有的成员(成员方法和成员变量)

其实这也体现了继承的另一个弊端:打破了封装性

子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。

不要为了部分功能而去继承

什么时候使用继承?

继承中类之间体现的是:”is a”的关系。

Java中的继承特点

1:继承关系是传递的。若类C继承类B,类B继承类A(多继承),则类C既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性与方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。

2:继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。

3:继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与基类(A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。

4:继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。

5:提供多重继承机制。从理论上说,一个类可以使多个一般类的特殊类,它可以从多个一般类中继承属性与方法,这便是多重继承。Java出于安全性和可靠性的考虑,仅支持单重继承,而通过使用接口机制来实现多重继承。

java中继承的注意事项

子类只能继承父类所有非私有的成员(成员方法和成员变量)

其实这也体现了继承的另一个弊端:打破了封装性

子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。

不要为了部分功能而去继承

 

什么时候使用继承呢?

继承中类之间体现的是:”is a”的关系。

如:

Person

Student 学生是一个人

Teacher 老师是一个人

水果

菠萝 菠萝是一个水果

草莓 草莓是一个水果

白菜 它不能继承 

继承中成员变量的关系

在子类方法中访问一个变量

首先在子类局部范围找

然后在子类成员范围找

最后在父类成员范围找(肯定不能访问到父类局部范围)

如果还是没有就报错。(不考虑父亲的父亲…)

如:

class Father {

int num = 10;

}

 

class Son extends Father {

int num2 = 20;

int num = 30;

 

public void show(){

int num = 40;

System.out.println(num);//40

System.out.println(num2);//20

}

}

 

 

class ExtendsDemo5 {

public static void main(String[] args) {

Son s = new Son();

s.show();

}

}

如果我要访问父类的成员方法用super关键字

 

 

thissuper分别是什么,他们各自的应用场景是什么?

 

this是什么?this代表本类对应的引用

比如说吃饭这个方法它是由上帝来定义的,世界上所有的人来执行。吃饭这个行为发生的时候,主体就是在吃饭的这个人,也就是要有人执行吃饭这个行为。有时候我们需要在一个行为(方法)里,能够明确知道这个行为是谁来执行的,确切的说就是我要知道谁在吃饭。

public void eatSomthing(){ 

System.out.println( this.eat );

}

在我们定义的每一个方法里,都会有一个this关键字,这个this关键不由在那儿定义来决定的,而是由谁来执行的决定的。这是判断this的关键。

 

super是什么?super代表父类存储空间的标识(可以理解为父类引用)

调用父类的属性,一个类中如果有int x属性,如果其子类中也可以了int x属性的话,在子类中调用父类的x属性时,应使用 super.x = 6,表示该x是引用的父类的属性,而要表示子类中的x属性的话,使用this.x

Java里的子类中用super调用父类构造函数时,调用的函数必须放在子类的第一条语句的位置

 继承中构造方法的关系

子类中所有的构造方法默认都会访问父类中空参数的构造方法

为什么呢?

因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。

每一个构造方法的第一条语句默认都是:super()

如果父类中没有空参数构造方法,该怎么办呢?

1: 手动给父类中加上 空参数构造方法

2: a:在子类的构造方法中的第一行 写上 super(参数列表),访问父类中有参数的构造方法b:在子类的构造方法中的第一行 写上 this(参数列表),访问子类中其他的构造方法,然后在其他的构造方法中再去访问父类构造方法

 

继承中成员方法的关系

1:在父类中定义一个成员方法

2:在子类中定义一个成员方法和父类中成员方法名称不同,然后在测试类中通过子类对象去访问方法,发现方法名不同,访问子类的成员方法

3:在子类中再定义一个成员方法,和父类中的成员方法名称一致,然后继续访问。发现访问的是子类的成员方法。

4:如果我要访问父类的成员方法用super关键字即 super.父类的方法

方法重写概述

子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。

使用特点:

如果方法名不同,就调用对应的方法

如果方法名相同,最终使用的是子类自己的

方法重写的应用:

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

方法重写的注意事项

父类中私有方法不能被重写

子类重写父类方法时,访问权限不能更低

父类静态方法,子类也必须通过静态方法进行重写。

举例:

class Father {

private void method(){

System.out.println("父类method方法");

}

 

public void function(){}

//void function(){}

 

//静态方法

public static void show(){ }

}

class Son extends Father {

public void method(){

 

//super.method();//访问父类中的method方法

//错误: method()可以在Father中访问private

 

System.out.println("子类method方法");

}

public void function(){}

//void function(){}//错误: Son中的function()无法覆盖Father中的function()

 

//静态方法

public static void show(){ }

//public void show(){ }//错误: Son中的show()无法覆盖Father中的show() ,被覆盖的方法为static

}

 

class ExtendsDemo11 {

public static void main(String[] args) {

//创建子类对象

Son s = new Son();

s.method();

}

}

1、方法重写和重载有什么区别?

答案:

重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)

重写Override表示子类中的方法可以与父类的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更少。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。

父类中成员private修饰,子类如何访问呢

用在父类中声明setXXXgetXXX方法

举例:

/*

学生案例和老师案例讲解

使用继承前

学生类

姓名,年龄,学号

睡觉()

学习(),打游戏()

 

(作业)老师类

姓名,年龄,工号

睡觉()

讲课(),做饭()

*/

/*

class 学生类 {

private String id;

private String 姓名;

private int 年龄;

//构造方法

public 学生类(){}

public 学生类(String id, String 姓名, int 年龄){

this.id = id;

this.姓名 姓名;

this.年龄 年龄;

}

 

//setXxx()  getXxx()

 

//提供一个show方法,用来显示打印 学生类对象中的成员

public void show(){

System.out.println(id + "---" + 姓名 + "---" + 年龄);

}

 

}

 

class 老师类 {

}

*/

 

class Student {

//成员变量

private String id;//学号

private String name;//姓名

private int age;//年龄

 

//构造方法

public Student(){}

public Student(String id, String name, int age){

this.id = id;

this.name = name;

this.age = age;

}

 

//提供setXxx() getXxx();

public void setId(String id){

this.id = id;

}

public String getId(){

return id;

}

public void setName(String name){

this.name = name;

}

public String getName(){

return name;

}

public void setAge(int age){

this.age = age;

}

public int getAge(){

return age;

}

//提供一个show方法,用来显示打印 学生类对象中的成员

public void show(){

System.out.println(id + "---" + name + "---" + age);

}

 

//睡觉()

public void sleep(){

System.out.println("睡觉");

}

 

//学习()

public void study(){

System.out.println("学习");

}

 

//打游戏()

public void playGame(){

System.out.println("英雄联盟");

}

}

 

class ExtendsDemo12 {

public static void main(String[] args) {

//创建对象

Student s = new Student("01", "李四", 20);

s.show();

s.sleep();

s.study();

s.playGame();

}

}

 

final关键字

final关键字是最终的意思,可以修饰类,成员变量,成员方法。

修饰类,类不能被继承

修饰变量,变量就变成了常量,只能被赋值一次

修饰方法,方法不能被重写

注:通过子类重写父类方法,来说明父类不能被人动的方法,也别动了。为了强制不能动,Java就提高了final关键字



http://blog.csdn.net/liu1pan2min3/article/details/44919569