尚硅谷Java基础学习笔记:面向对象(上)(第四章)

学习面向对象的三条主线:
1、Java类及类的成员
Java有类和对象两大要素,其中对象也是由类派生的,所以我们更关心类的设计
设计类的即设计类的成员,类的成员包括:属性、方法、构造器、代码块、内部类(前三者比较重要)
2、面向对象的三大特征
封装性、继承性、多态性(如果说到第四个特征那么就是抽象性)
3、其他关键字
this、super、static、final、abstract、interface、package、import等

一、面向过程与面向对象

1、何为“面向对象”的编程思想?

首先,思想的定义:像做一个孝顺、爱国、善良人,是做人的思想,或者说是做人的原则。编程也有编程的原则,这些编程原则,即编程思想。做人的原则体现到人具体的行为上,就如编程思想体现到具体的编程实现上。

2、面向过程(POP)与面向对象(OOP)

  • 二者都是一种思想,面向对象是相对于面向过程而言的。
    面向过程(Object Oriented Programming):强调的是功能行为,以函数为最小单位,考虑怎么做。
    面向对象(Procedure Oriented Programming):将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
  • 面向对象更加强调运用人类在日常的逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态

3、面向对象的三大特征

  • 封装(Encapsulation)
  • 继承(Inheritance)
  • 多态(Polymorphism)

4、例子:人把大象装进冰箱

在这里插入图片描述

5、面向对象的思想概述

  • 程序员从面向过程的执行者转换成了面向对象的指挥者
  • 面向对象分析方法分析问题的思路和步骤:
    (1)根据问题需要,选择问题所针对的现实世界中的实体
    (2)从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类
    (3)把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义,即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构
    (4)将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的工具

二、Java基本元素:类和对象

1、面向对象的思想概述

  • 面向对象的核心概念:类(Class)和对象(Object)
    (1)类是对一类事物的描述,是抽象的、概念上的定义
    (2)对象是实际存在的该类事物的每个个体,因而也称实例(instance)
  • “万事万物皆对象”
    (1)在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
    如使用到的Scanner,String类;文件:File;网络资源:URL
    (2)涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象
  • 可以理解为:类 = 抽象概念的人;对象 = 实实在在的某个人
  • 面向对象程序设计的重点是类的设计,而类的设计其实就是类的成员的设计

2、Java类及类的成员

  • 现实世界的生物体,都是由最基本的细胞构成。同理,Java代码世界是由诸多个不同功能的构成
  • 现实世界中的细胞又由细胞核、细胞质…构成。同理,Java中用类class来描述事物也是如。常见的类的成员:
    (1)属性(Filed,又域、字段):对应类中的成员变量
    (2)行为(Method):对应类中的成员方法
    在这里插入图片描述
    在这里插入图片描述

3、类的语法格式

在这里插入图片描述

4、创建Java自定义类的步骤

  • 定义类(考虑修饰符、类名)
  • 编写类的属性(考虑修饰符、属性类型、属性名、初始化值)
  • 编写类的方法(考虑修饰符、返回值类型、方法名、形参等)

三、对象的创建和使用

1、使用Java类的方法

  • 通过类的实例化,即创建类的对象使用Java类的方法
    创建对象:类名 对象名 = new 类名();
    访问对象成员的属性或方法:对象名.对象成员
    在这里插入图片描述
    在这里插入图片描述
  • 如果创建了一个类的多个对象,对于类中定义的属性,每个对象都拥有各自的一套副本,互不干扰
    在这里插入图片描述

2、类的访问机制

  • ==在一个类中的访问机制:==类中的方法可以直接访问类中的成员变量(但static方法访问非static方法编译不通过
  • ==在不同类中的访问机制:==先创建要访问类的对象,再用对象访问类中定义的成员

3、对象的内存解析

编译完源程序以后,生成一个或多个字节码文件。我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行,解释运行意味着要把字节码文件中的对应类加载到内存中,涉及到内存解析。
下图为Java虚拟机所规定的内存结构,我们主要关注运行时数据区(包含方法区、虚拟机栈、本地方法栈、堆、程序计数器这几个结构)
在这里插入图片描述

  • 堆(Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
  • 通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于==存储局部变量(所有方法中的变量都是局部变量)==等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完毕,自动释放。
  • 方法区(Method Area),用于存储已被虚拟机加载的类信息、常量(如字符串常量池)、静态变量(即静态域static)、即时编译器编译后的代码等数据。
  • 实例1
    在这里插入图片描述
    (1)Person p1 = new Person();
    new操作:在堆空间中创建实体,并分配内存,内存首地址值为0x12ab,其中内存包含实体类所定义的三个属性(创建对象时会自动给成员变量赋值,由于三个属性中isMale默认为false,age默认为1,name没有默认值所以为null)
    p1的定义及赋值操作:在栈空间中定义一个局部变量p1,将new出来对象的内存首地址赋值给p1。通过这个地址值,栈空间中的p1就指向了堆空间中创建的person实体
    (2)p1.name = “Tom”;
    通过占空间中的p1去调用name属性,改成Tom(Tom实际上存放于字符串常量池,在方法区内)
    (3)p1.isMale = true;
    通过占空间中的p1去调用isMale,改成true
    (4)Person p2 = new Person();
    同(1),内存地址为0x7788
    (5)sysout(p2.name);//null
    (6)Person p3 = p1;
    p3的定义及赋值操作:在栈空间中定义一个局部变量p3,将p1对象的内存首地址赋值给p3。通过这个地址值,栈空间中的p3就指向了堆空间中创建的person实体(p3不能说是新创建了一个对象,只能说是新声明了一个变量),此时p1和p3指向了堆空间中的同一个对象实体
    (7)p3.age = 10;
    p3修改了age,p1再去调,得到的是修改之后的age
    (8)当方法运行完毕,栈空间中的所有局部变量都被清空;而堆空间剩下的对象没有被任何指针指向,会被当成垃圾回收
  • 实例2
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意最后这张图:当将null赋值给p1时,此时p1和p2不再指向堆空间中的同一个对象实体

4、匿名对象

  • 我们也可以不定义对象的句柄,而直接调用这个对象的方法,这样的对象交匿名对象
    如:new Person().shout();
  • 使用情况:
    如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象
    我们经常将匿名对象作为实参传递给一个方法调用

四、类的成员之一:属性(field)

1、语法格式

  • 语法:修饰符 数据类型 属性名 = 初始化值;
    (1)修饰符:常用的权限修饰符有private、缺省(默认)、protected、public;其他修饰符如static、final暂不考虑
    (2)数据类型:任何基本数据类型(如int、Boolean)或任何引用数据类型
    (3)属性名:属于标识符,符合命名规则和规范即可
  • 举例
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}

2、变量的分类(成员变量与局部变量)

  • 在方法体外,类体内声明的变量称为成员变量
    在方法体内部声明的变量称为局部变量
  • 成员变量(属性):包括实例变量(不以static修饰)和类变量(以static修饰)
    局部变量:包括形参(方法、构造器中定义的变量)、方法局部变量(在方法内定义)、代码块局部变量(在代码块内定义)
  • 两者在初始值方面的异同
    同:都有生命周期
    异:局部变量除形参外,均需显式初始化(赋值)

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

成员变量局部变量
声明的位置直接声明在类中方法形参或内部、代码块内、构造器内等
修饰符private、public、static、final等不能用权限修饰符修饰,可以用final修饰
初始化值有默认值没有默认值,必须显式赋值,方可使用
内存加载位置堆空间或静态域内(static区)栈空间

4、成员变量与局部变量的内存位置

在这里插入图片描述

5、对象属性的默认初始化赋值

当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型,如上面的Person及前面讲过的数组
在这里插入图片描述

6、数组对象的内存解析

在这里插入图片描述
在这里插入图片描述

五、类的成员之二:方法(Method)

1、方法(Method、函数)的定义

  • (1)方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程
    (2)将功能封装为方法的目的:实现代码重用,简化代码
    (3)Java里的方法不能独立存在,所有的方法必须定义在类里
  • 例子
    在这里插入图片描述

2、方法的声明语法

  • 修饰符 返回值类型 方法名 (参数类型 形参1,参数类型 形参2,…){
    方法体程序代码
    return 返回值;
    }

    (1)修饰符:public、缺省、private、protected
    (2)返回值类型:没有返回值为void;有返回值,声明出返回值的类型,与方法体中“return 返回值”搭配使用
    (3)方法名:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”
    (4)形参列表:可以包含零个、一个或多个参数。多个参数时,中间用“,”隔开
    (5)返回值:方法在执行完毕后返回给调用它的程序的数据

3、方法的分类

分类标准:按照有无形参及有无返回值
在这里插入图片描述

4、方法的调用

  • 方法通过方法名被调用,且只有被调用才会被执行
  • 方法调用的过程分析
    在这里插入图片描述
  • 注意
    (1)方法被调用一次,就会执行一次
    (2)没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中通常不使用return语句。如果使用,仅用来结束方法,结束方法后不可以再声明、执行语句
    (3)定义方法时,方法的结果应该返回(return)给调用者,交由调用者处理
    (4)方法中只能调用当前类的方法或属性,不可以在方法内部定义方法

5、使用递归导致栈溢出(Stack OverflowError)

public void sleep(int hour){
	sout("休息了" + hour + "个小时")eat();
	sleep(10);
}

死循环,不断调用sleep(),不断声明新hour局部变量,栈内存空间保爆炸
结论:虽然Java中有垃圾回收机制,但是错误的调用方式也会导致内存溢出

六、再谈方法

1、方法的重载(Overload)

  • 重载的概念:
    在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可(取决于类名、方法名和参数列表)
  • 重载的特点:
    与权限修饰符、返回值类型、形参变量名、方法体无关,只看参数列表,且参数列表(参数个数或参数类型)必须不同。调用时,根据方法参数列表的不同来区别
  • 示例
    (1)示例1
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
double add(double x,double y){return x+y;}

(2)示例2

public class PrintStream {
	public static void print(int i) {……}
	public static void print(float f) {……}
	public static void print(String s) {……}
	
	public static void main(String[] args) {
		print(3);
		print(1.2f);
		print("hello!");
	}
}
  • 重载的好处:为编程带来方便
    如System.out.printIn()方法就是最典型的重载方法,其内部声明格式:
public void println(byte x)
public void println(short x)
public void println(int x)
public void println(long x)
public void println(float x)
public void println(double x)
public void println(char x)
public void println(double x)
public void println()
……

2、可变形参的方法

JavaSE 5.0中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的形参。

//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public static void test(int a,String[] books);
//JDK 5.0:采用可变个数形参来定义方法,传入多个同一类型变量

说明
(1)声明格式:方法名(参数的类型名…参数名)
(2)可变形参:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
(3)可变形参的方法与同名的方法之间,彼此构成重载
(4)可变形参方法的使用与方法参数部分使用数组是一致的(不可以同时写两个;遍历方式一样)
(5)在一个方法的形参位置,最多只能声明一个可变形参;且可变形参必须放在参数列表的最后(如果有多个可变形参或可变形参不在形参列表的最后,就不能分清各个可变形参所覆盖的范围)
(6)使用场景:当用户想要查找数据库的某些数据,我们不知道要查找的数据具体是什么以及要查找几个,这时候可变形参就发回发挥出作用

public void test(String[] msg){
	System.out.println(“含字符串数组参数的test方法 ");
}
public void test1(String book){
	System.out.println(****与可变形参方法构成重载的test1方法****");
}
public void test1(String ... books){
	System.out.println("****形参长度可变的test1方法****");
}
public static void main(String[] args){
	TestOverload to = new TestOverload();
	//下面两次调用将执行第二个test方法
	to.test1();
	to.test1("aa" , "bb");
	//下面将执行第一个test方法
	to.test(new String[]{"aa"});
}

*3、方法参数的值传递机制

  • (1)方法必须由其所在类或对象调用才有意义,方法含有的参数分为形参(方法声明时的参数)和实参(方法调用时实际传给形参的参数值)
    (2)Java的实参值传入方法的过程:Java里方法的参数传递方式只有一种,称为值传递,即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
    形参为基本数据类型,将实参基本数据类型变量的“数据值”传递给形参
    形参为引用数据类型,将实参引用数据类型变量的“地址”值传递给形参

  • 基本数据类型的参数传递

public static void main(String[] args) {
	int x = 5;
	System.out.println("修改之前x = " + x);// 5
	// x是实参
	change(x);
	System.out.println("修改之后x = " + x);// 5
}
public static void change(int x) {
	System.out.println("change:修改之前x = " + x);
	x = 3;
	System.out.println("change:修改之后x = " + x);
}

在这里插入图片描述

  • 引用数据类型的参数传递
    (1)示例1
public static void main(String[] args) {
	Person obj = new Person();
	obj.age = 5;
	System.out.println("修改之前age = " + obj.age);// 5
	// x是实参
	change(obj);
	System.out.println("修改之后age = " + obj.age);// 3
}
public static void change(Person obj) {
	System.out.println("change:修改之前age = " + obj.age);
	obj.age = 3;
	System.out.println("change:修改之后age = " + obj.age);
}

其中Person类定义为:
class Person{
	int age; 
} 

在这里插入图片描述
(2)示例2

public static void main(String[] args) {
	Person obj = new Person();
	obj.age = 5;
	System.out.println("修改之前age = " + obj.age);// 5
	// x是实参
	change(obj);
	System.out.println("修改之后age = " + obj.age);// 5
}
public static void change(Person obj) {
	obj = new Person();
	System.out.println("change:修改之前age = " + obj.age);
	obj.age = 3;
	System.out.println("change:修改之后age = " + obj.age);
}

其中Person类定义为:
class Person{
	int age; 
}

在这里插入图片描述

  • 例题
    (1)例题3
public class TransferTest3 {
		public static void main(String args[]) {
		TransferTest3 test = new TransferTest3();
		test.first();
	}
	public void first() {
		int i = 5;
		Value v = new Value();
		v.i = 25;
		second(v, i);
		System.out.println(v.i);
	}
	public void second(Value v, int i) {
		i = 0;
		v.i = 20;
		Value val = new Value();
		v = val;
		System.out.println(v.i + " " + i);
	}
}

class Value {
int i = 15;
}

在这里插入图片描述
(2)例题5 —— 脑筋急转弯
在这里插入图片描述
方法1:使用exit()退出程序

    private static void method(int a, int b) {
        a = a*10;
        b = b*20;
        System.out.println(a);
        System.out.println(b);
        //exit()退出程序,终止当前JVM的执行
        System.exit(0);
    }

方法2:重写println()方法

    private static void method(int a, int b) {
        PrintStream ps = new PrintStream(System.out){
            @Override
            public void println(String x){
                if("a=10".equals(x)){
                    x = "a=100";
                }else if("b=10".equals(x)){
                    x="b=200";
                }
                super.println(x);
            }
        };
    }

(3)例题6
定义一个int型的数组:int[] arr = new int[]{12,3,3,34,56,77,432};让数组的每个位置上的值去除以首位置的元素,得到的结果,作为该位置上的新值。遍历新的数组。
错误写法:

for(int i= 0;i < arr.length;i++){
arr[i] = arr[i] / arr[0];
}

正确写法:

//法1
for(int i = arr.length – 1;i >= 0;i--){
arr[i] = arr[i] / arr[0];
}
//法2
int temp = arr[0];
for(int i= 0;i < arr.length;i++){
arr[i] = arr[i] / temp;
}

4、递归方法

七、OOP特征一:封装与隐藏

八、类的成员之三:构造器

九、关键字:this

十、关键字:package、import

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值