1.面向对象编程
面向过程(Procedure Oriented)是一种以过程为中心的编程思想,它关注的是将问题分解成一个个详细的步骤,并通过函数实现每一个步骤,然后依次调用这些函数来解决问题。常见的面向过程的语言有C语言。
面向对象编程(Object-Oriented Programming,简称OOP)是一种计算机编程模型,它围绕数据或对象来组织软件设计,而不是围绕功能和逻辑。在面向对象的编程中,更强调对象与对象之间的交互,对象的属性和方法都被封装在对象内部。面向对象编程具有封装性、继承性和多态性三大特性。常见的面向对象的语言有Java,Python,PHP等。
举例:到超市购物,超市有500种商品,买了6样商品
面向过程思考:到超市购物,买了6样商品,回家放入冰箱
面向对象思考:到超市购物,超市所有商品创建实体,买了6样商品,回家放入冰箱
需求变更:
面向过程:又买了猪肉,修改代码,才能放入冰箱
面向对象:猪肉实体已经买了,无需修改代码,就把猪肉放入冰箱即可
1.2 类和对象
1.2.1 什么是类
类是一类具有相同特性的事物的抽象描述,是一组相关属性和行为的集合。
-
属性:就是该事物的状态信息。
- 行为:就是在你这个程序中,该状态信息要做什么操作,或者基于事物的状态能做什么。
1.2.2 什么是对象
对象是一类事物的一个具体个体(对象并不是找个女朋友)。即对象是类的一个实例,必然具备该类事物的属性和行为。
1.2.3 类和对象的关系
-
类是对一类事物的描述,是抽象的。是相同属性和方法的一组对象的集合。
-
对象是一类事物的实例,是具体的。
-
类是对象的模板,对象是类的实体。是能够看的到,摸得到的具体实体。
-
世间万物皆对象
1.3 如何定义类
1.3.1 类的定义格式
关键字:class(小写)
【修饰符】 class 类名{
}
类的定义格式举例:
public class Student{
}
1.3.2 对象的创建
关键字:new
new 类名()//也称为匿名对象
//给创建的对象命名
//或者说,把创建的对象用一个引用数据类型的变量保存起来,这样就可以反复使用这个对象了
类名 对象名 = new 类名();
对象名中存储的是什么呢?答:对象地址
int[] arr = new int[5];
System.out.println(arr);//[I@70dea4e
发现学生对象和数组对象类似,直接打印对象名和数组名都是显示“类型@对象的hashCode值",所以说类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址。
那么像“Student@4e25154f”是对象的地址吗?不是,因为Java是对程序员隐藏内存地址的,不暴露内存地址信息,所以打印对象时不直接显示内存地址,而是JVM帮你调用了对象的toString方法,将对象的基本信息转换为字符串并返回,默认toString方法返回的是“对象的运行时类型@对象的hashCode值的十六进制值”,程序员可以自己改写toString方法的代码(后面会讲如何改写)。
类: 人、猫、狗等
// 猫
public class Cat {
// 属性
String nickName;
int age;
String color;
// 方法 void(没有返回值) 修饰符 返回的数据类型 方法名
public String call() {
return "喵喵喵!";
}
public void showInfo() {
System.out.println("我的名字叫:" + nickName + ",今年" + age + "岁了,我是一只" + color + "的小猫咪!");
}
}
// 狗
public class Dog {
// 属性
// 昵称
String nickname;
// 狗的类型
String type;
int energy;
// 常量 常量在命令规范上使用全部大写,不可更改的量
final int MAX_ENERGY = 120;
// 行为 方法
public int eat() {
if (energy < MAX_ENERGY) {
energy += 10;
return energy;
}
return energy;
}
}
// 人
public class Person {
// 属性
String userName;
boolean sex;
// 拥有狗的属性
Dog dog;
public void feed() {
System.out.println(dog.eat());
}
}
2.包
2.1 包的作用
(1)可以避免类重名:有了包之后,类的全名称就变为:包.类名
(2)可以控制某些类型或成员的可见范围
如果某个类型或者成员的权限修饰缺省的话,那么就仅限于本包使用。
(3)分类组织管理众多的类
例如:
-
java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和Thread等,提供常用功能
-
java.net----包含执行与网络相关的操作的类和接口。
-
java.io ----包含能提供多种输入/输出功能的类。
-
java.util----包含一些实用工具类,如集合框架类、日期时间、数组工具类Arrays,文本扫描仪Scanner,随机值产生工具Random。
-
java.text----包含了一些java格式化相关的类
-
java.sql和javax.sql----包含了java进行JDBC数据库编程的相关类/接口
-
java.awt和java.swing----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
2.2 如何声明包
关键字:package
package 包名;
注意:
(1)必须在源文件的代码首行
(2)一个源文件只能有一个声明包的package语句
包的命名规范和习惯:
(1)所有单词都小写,每一个单词之间使用.分割
(2)习惯用公司的域名倒置开头
例如:com.haogu.xxx;
建议大家取包名时不要使用“java.xx"包
2.3 如何跨包使用类
注意:只有public的类才能被跨包使用
(1)使用类型的全名称
例如:java.util.Scanner input = new java.util.Scanner(System.in);
(2)使用import 语句之后,代码中使用简名称
import语句告诉编译器到哪里去寻找类。
import语句的语法格式:
import 包.类名;
import 包.*;
注意:
使用java.lang包下的类,不需要import语句,就直接可以使用简名称
import语句必须在package下面,class的上面
当使用两个不同包的同名类时,例如:java.util.Date和java.sql.Date。一个使用全名称,一个使用简名称
3.成员变量
3.1 如何声明成员变量
【修饰符】 class 类名{
【修饰符】 数据类型 成员变量名;
}
示例:
public class Person{
String name;
char gender;
int age;
}
位置要求:必须在类中,方法外
类型要求:可以是Java的任意类型,包括基本数据类型、引用数据类型(类、接口、数组等)
修饰符:成员变量的修饰符有很多,例如:public、protected、private、static、volatile、transient、final等,后面会一一学习。
其中static可以将成员变量分为两大类,静态变量和非静态变量。其中静态变量又称为类变量,非静态变量又称为实例变量或者属性。接下来先学习实例变量。
3.2 对象的实例变量
3.2.1 实例变量的特点
(1)实例变量的值是属于某个对象的
-
必须通过对象才能访问实例变量
-
每个对象的实例变量的值是独立的
(2)实例变量有默认值
分类 | 数据类型 | 默认值 |
---|---|---|
基本类型 | 整数(byte,short,int,long) | 0 |
浮点数(float,double) | 0.0 | |
字符(char) | '\u0000' | |
布尔(boolean) | false | |
数据类型 | 默认值 | |
引用类型 | 数组,类,接口 | null |
3.2.2 实例变量的访问
实例对象.实例变量
示例:
public class TestStudent01 {
public static void main(String[] args) {
// 使用类
// 如果想使用必然创建一个具体的对象 学生对象
// 使用 new 方法来创建对象
Student stu1 = new Student();
// 学生对象的地址值
System.out.println(stu1);
// 对象实例.访问属性/方法
// 对象实例.属性 ->属性值
// 对象实例.方法名() _>()来执行方法
stu1.StuName = "小许";
stu1.age = 19;
stu1.height = 190.3f;
System.out.println("学生 1 的名字是:" + stu1.StuName);
System.out.println("学生 1 的年龄是:" + stu1.age);
System.out.println("学生 1 的身高是:" + stu1.height);
// System.out.println(stu1.study());
stu1.study();
stu1.showInfo();
}
}
3.2.3 实例变量的内存分析
内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。Java虚拟机要运行程序,必须要对内存进行空间的分配和管理,每一片区域都有特定的处理数据方式和内存管理方式。
JVM的运行时内存区域分为:方法区、堆、虚拟机栈、本地方法栈、程序计数器几大块。
Java对象保存在内存中时,由以下三部分组成:
-
对象头
-
Mark Word:记录了和当前对象有关的GC、锁等信息。(后面再讲)
-
指向类的指针:每一个对象需要记录它是由哪个类创建出来的,而Java对象的类数据保存在方法区,指向类的指针就是记录创建该对象的类数据在方法区的首地址。该指针在32位JVM中的长度是32bit,在64位JVM中长度是64bit。
-
数组长度(只有数组对象才有)
-
-
实例数据
-
即实例变量的值
-
-
对齐填充
-
因为JVM要求Java对象占的内存大小应该是8bit的倍数,如果不满足该大小,则需要补齐至8bit的倍数,没有特别的功能。
-
3.3 静态成员
静态成员:
静态成员变量(由static修饰,内存加载一次):常表示在线人数需要被共享的信息,可以被共享访问。
同一类中静态成员变量的访问可以省略类名。同一个类中,访问静态方法,类名可以省略不写【这点就可以解释在主函数main中,可以不用写类名,直接写方法名就可以用这个方法。
使用场景区别:
实例方法:表示对象自己的行为,且方法中需要访问实例成员。
静态方法:如果该方法是以执行一个共用功能为目的。
内存原理:
当类被加载到方法区的时候,其静态方法也已经被加载了出来,但成员方法还暂时没有加载。 Main方法加载到栈内存,然后创建对象(在堆内存中创建对象,在栈内存中的main方法中存放着对象在堆内存的地址。)对象中包含着实例成员变量和实例成员方法(方法在方法引用中。)当需要用到方法时,实例方法会加载到方法区中。
4.方法
4.1 方法的概念
方法也叫函数,是一组代码语句的封装,从而实现代码重用,从而减少冗余代码,通常它是一个独立功能的定义,方法是一个类中最基本的功能单元。
Math.random()的random()方法;
4.2 方法的特点
(1)必须先声明后使用
类,变量,方法等都要先声明后使用
(2)不调用不执行,调用一次执行一次。
4.3 如何声明方法
4.3.1 声明方法的位置
声明方法的位置==必须在类中方法外==,即不能在一个方法中直接定义另一个方法。
声明位置示例:
类{
方法1(){
}
方法2(){
}
}
// 错误示例(方法不能嵌套)
类{
方法1(){
方法2(){ //位置错误
}
}
}
4.3.2 声明方法的语法格式
【修饰符】 返回值类型 方法名(【形参列表 】)【throws 异常列表】{
方法体的功能代码
}
(1)一个完整的方法 = 方法头 + 方法体。
-
方法头就是 【修饰符】 返回值类型 方法名(【形参列表 】)【throws 异常列表】,也称为方法签名,通常调用方法时只需要关注方法头就可以,从方法头可以看出这个方法的功能和调用格式。
-
方法体就是方法被调用后要指定的代码,也是完成方法功能的具体实现代码,对于调用者来说,不了解方法体如何实现的,并影响方法的使用。
(2)方法头可能包含5个部分,但是有些部分是可能缺省的
-
修饰符:可选的。方法的修饰符也有很多,例如:public、protected、private、static、abstract、native、final、synchronized等,后面会一一学习。其中根据是否有static,可以将方法分为静态方法和非静态方法。其中静态方法又称为类方法,非静态方法又称为实例方法。==接下来咱们先学习实例方法==。
返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者
-
基本数据类型
-
引用数据类型
-
无返回值类型:void
方法名:给方法起一个名字,见名知意,能准确代表该方法功能的名字
参数列表:表示完成方法体功能时需要外部提供的数据列表
-
无论是否有参数,()不能省略
-
如果有参数,每一个参数都要指定数据类型和参数名,多个参数之间使用逗号分隔,例如:
-
一个参数: (数据类型 参数名)
-
二个参数: (数据类型1 参数1, 数据类型2 参数2)
-
-
参数的类型可以是基本数据类型、引用数据类型
-
throws 异常列表:可选,在异常章节再讲
(3)方法体:方法体必须有{}括起来,在{}中编写完成方法功能的代码
关于方法体中return语句的说明:
-
return语句的作用是结束方法的执行,并将方法的结果返回去
-
如果返回值类型不是void,方法体中必须保证一定有 return 返回值; 语句,并且要求该返回值结果的类型与声明的返回值类型一致或兼容。
-
如果返回值类型为void时,方法体中可以没有return语句,如果要用return语句提前结束方法的执行,那么return后面不能跟返回值,直接写return ; 就可以。
-
return语句后面就不能再写其他代码了,否则会报错:Unreachable code
public class MethodDefineDemo {
// 2。有参无返回
// 3.无参无返回
// 4.有参有返回
// 1.无参有返回
public void sayHello() {
System.out.println("hello world");
}
}
public class MainClass2 {
public static void main(String[] args) {
// 必须先声明再使用
// 不能方法嵌套
MethodDefineDemo MethodDefineDemo = new MethodDefineDemo();
// 调用: 对象名.方法名(实参);
// 1.无参,无返回
MethodDefineDemo.sayHello();
}
}
4.4 如何调用实例方法
4.4.1 方法调用语法格式
对象.非静态方法(【实参列表】)
MethodDefineDemo MethodDefineDemo = new MethodDefineDemo();
// 调用: 对象名.方法名(实参);
// 1.无参,无返回
MethodDefineDemo.sayHello();
4.4.2 形参和实参
-
形参(formal parameter):在定义方法时方法名后面括号中声明的变量称为形式参数(简称形参)即形参出现在方法定义时。
-
实参(actual parameter):调用方法时方法名后面括号中的使用的值/变量/表达式称为实际参数(简称实参)即实参出现在方法调用时。
-
调用时,实参的个数、类型、顺序顺序要与形参列表一一对应。如果方法没有形参,就不需要也不能传实参。
-
无论是否有参数,声明方法和调用方法是()都不能丢失
4.4.3 返回值问题
方法调用表达式是一个特殊的表达式:
-
如果被调用方法的返回值类型是void,调用时不需要也不能接收和处理(打印或参与计算)返回值结果,即方法调用表达式==只能==直接加;成为一个独立语句。
-
如果被调用方法有返回值,即返回值类型不是void,
-
方法调用表达式的结果可以作为赋值表达式的值,
-
方法调用表达式的结果可以作为计算表达式的一个操作数,
-
方法调用表达式的结果可以作为另一次方法调用的实参,
-
方法调用表达式的结果可以不接收和处理,方法调用表达式直接加;成为一个独立的语句,这种情况,返回值丢失。
-
4.5 实例方法使用当前对象的成员
在实例方法中还可以使用当前对象的其他成员。在Java中当前对象用this表示。
-
this:在实例方法中,表示调用该方法的对象
-
如果没有歧义,完全可以省略this。
4.5.1 this 省略与不省略
public class Shop {
public String pic;
public String title;
public double price;
public int count;
public void changedCount(int number) {
// 有参无返回
this.count = number;
}
// this 可以省略不写
public void changedCount2(int number) {
count = number;
}
// this 不可以省略 形参与属性名相同
public void changedCount3(int count) {
// count 代表形参
// this.count 代表属性
this.count = count;
}
}
4.6 方法调用内存分析
-
方法不调用不执行,调用一次执行一次;
-
每次调用会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值,当方法执行结束后,会释放该内存,称为出栈;
-
如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。
栈结构:先进后出,后进先出。
4.7 实例变量与局部变量的区别
1、声明位置和方式
(1)实例变量:在类中方法外
(2)局部变量:在方法体{}中或方法的形参列表、代码块中
2、在内存中存储的位置不同
(1)实例变量:堆
(2)局部变量:栈
3、生命周期
(1)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的。
(2)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡, 而且每一次方法调用都是独立。
4、作用域
(1)实例变量:通过对象就可以使用,本类中“this.,没有歧义还可以省略this.”,其他类中“对象.” (2)局部变量:出了作用域就不能使用
5、修饰符(后面来讲)
(1)实例变量:public,protected,private,final等
(2)局部变量:final
6、默认值
(1)实例变量:有默认值
(2)局部变量:没有,必须手动初始化。其中的形参比较特殊,靠实参给它初始化。
后续内容,正在更新...