JAVA 面向对象-上 (一)
类与对象
1.面向对象学习的三条主线:
①Java类及类的成员:属性、方法、构造器;代码块、内部类
②面向对象的三大特征:封装性、继承性、多态性、(抽象性)
③其他关键字:this,super,abstract,final,static,import,interface,package等
“大处着眼,小处着手”
2.面向对象与面向过程(理解)
1.面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
2.面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
//面向过程
/*①把冰箱打开
* ②抬起大象,塞进冰箱
* ③把冰箱门关闭
*/
//面向对象
/*人{
* 打开(冰箱门){
* 冰箱.开开();
* }
* 抬起(大象){
* 大象.进入(冰箱);
* }
* 关闭(冰箱){
* 冰箱.闭合();
* }
* }
* 冰箱{
* 开开(){}
* 闭合(){}
* }
*
* 大象{
* 进入(冰箱){
*
* }
* }
*/
3.完成一个项目(或功能)的思路:
根据问题需要,选择问题所针对的现实世界中的实体。
从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
4.面向对象中两个重要的概念
类:对一类事物的描述,是抽象的、概念上的定义
对象:是实际存在的该类实物的每个个体,因而也称为实例(instance)
--面向对象程序设计的重点是类的设计
--设计类,就是设计类的成员
二者的关系:
对象,是由类new出来的,派生出来的。
5.面向对象思想落地实现的规则
1.创建类,设计类的成员
2.创建类的对象
3.通过“对象.属性”或“对象.方法”调用对象的结构
补充:几个概念的使用说明
属性=成员变量=field=域、字段
方法=成员方法=函数=method
创建类的对象=类的实例化=实例化类
6.对象的创建与对象的内存解析
典型代码:
Person p1=new Person();
Person p2=new Person();
Person p3=p1;//没有新创建一个对象,共用一个堆空间中的对象实体。
说明:
如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
意味着:如果我们修改一个对象的属性a,则不影响另一个对象属性a的值
7.匿名对象:
理解:我们创建的对象,没有显式的赋给一个变量名,即为匿名对象。
特征:匿名对象只能调用一次。
举例:
//匿名对象
new Phone().sendEmail();
new Phone().playGame();
new Phone().price=1999;
new Phone().showPrice();//0.0
应用场景:
PhoneMall mall=new PhoneMall();
//匿名对象的使用
mall.show(new Phone());
//其中
class PhoneMall{
public void show(Phone phone) {
phone.sendEmail();
phone.playGame();
}
}
8.理解”万事万物皆对象“
1.在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
Scanner,String等
文件:File
网络资源:URL
2.涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。
9.JVM内存结构
编译完源程序以后,生成一个或多个字节码文件。
我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
推荐书籍:《JVM规范》
虚拟机栈,即为平时提到的栈结构。我们将局部变量存储在栈结构中。
堆:我们将new出来的结构(比如:数组、对象)加载在堆空间中。补充:对象的属性(非static中)加载在堆空间中。
方法区:类的加载信息、常量池、静态域
类的结构之一:属性
类中属性的使用
属性(成员变量)VS局部变量
1.相同点:
1.1定义变量的格式:数据类型 变量名=变量值
1.2先声明,后使用
1.3变量都有其对应的作用域
2.不同点:
2.1在类中声明的位置的不同
属性:直接定义在类的一对{}中
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.2关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符
常用的权限修饰符:private、public、确省、protected------>封装性
局部变量:不可以使用权限修饰符
2.3默认初始化值的情况:
属性:类的属性,根据其类型,都有默认初始化值。
整型(byte、short、int、long):0
浮点型(float、double):0.0
字符型(char):0(或'\u0000')
布尔型(boolean):false
引用数据类型(类、数组、接口):null
局部变量:没有默认初始化值
意味着,我们在调用局部变量之前,一定要显式赋值。
特别地:形参在调用时,我们赋值即可
2.4在内存中加载的位置
属性:加载到堆空间中(非static)
局部变量:加载到栈空间.
类的结构之二:方法
类中方法的声明和使用
方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\。。。。
Scanner类:nextXxx().......
Array类:sort()\binarySearch()\toString()\quals()\。。。。。
1.举例:
public void eat(){}
public void sleep(int hour){}
public String getName(){}
public String getNation(String nation){}
2.方法的声明:权限修饰符 返回值类型 方法名(形参列表){
方法体;
}
注意:static、final、abstract来修饰的方法,后面再讲
3.说明:
3.1关于权限修饰符:默认方法的权限修饰符先都使用public
Java规定的4种权限修饰符:public、private、缺省、protected--->封装性再细说
3.2返回值类型: 返回值 VS 没返回值
3.2.1如果方法返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”
如果方法没返回值,则方法声明时,使用void来表示,通常,没返回值的方法中,就不需要使用return。但是,如果使用的话,只能“return”,表示结束此方法的意思。
3.2.2我们定义方法该不该返回值?
①根据题目要求
②凭经验:具体问题具体分析
3.3方法名:属于标识符,遵循标识符的规则和规范:“见名知意”
3.4形参列表:方法可以声明0个、1个或多个形参
3.4.1格式:数据类型1 形参1,数据类型2 形参2,.....
3.4.2我们定义方法是,该不该定义形参?
①根据题目要求
②凭经验:具体问题具体分析
3.5方法体:方法功能的实现
4.return关键字的使用
1.适用范围:使用在方法体中
2.作用:①结束方法
②针对有返回值类型的方法,使用“return 数据”方法返回所要的数据
3.注意点:return关键字后不可以声明执行语句。
5.方法的使用中,可以调用当前类的属性或方法。
特殊的:方法A中又调用了方法A:递归方法。
方法中,不可以定义方法。
方法的重载
1.方法的重载的概念
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
"两同一不同":同一个类,相同方法名
参数列表不同:参数个数不同,参数类型不同
2.构成重载的举例:
举例一:Arrays类中重载sort()/binarySearch();
举例二:
//如下的4个方法构成了重载
public void getSum(int i,int j) {
System.out.println("1");
}
public void getSum(double d1,double d2) {
System.out.println("2");
}
public void getSum(String s,int i) {
System.out.println("3");
}
public void getSum(int i,String s) {
System.out.println("4");
}
不构成重载的举例:
//错误重载,下列三种不能与上述4个方法构成重载
/*
public int getSum(int i,int j) {
return 0;
}
*/
/*public void getSum(int m,int n) {
}
*/
// private void getSum(int i,int j) {
//
// }
3.如何判断是否构成方法的重载?
严格按照定义判断:两同一不同。
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
4.如何确定类中某一个方法的调用
方法名---->参数列表
面试题:方法的重载于重写的区别?
throws\throw
String\stringBuffer\StringBuilder
collection\collections
final \finally\finalize
............
抽象类、接口
sleep()/wait()
可变个数形参的方法
1.使用说明
1.jdk 5.0新增的内容
2.具体使用
2.1可变个数形参的格式:数据类型...变量名
2.2当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个.....
2.3可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
2.4可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。即,不可共存
2.5可变个数形参在方法的形参中,必须声明在末尾
2.6可变个数形参在方法的形参中,最多只能声明一个可变形参
2.举例说明:
public void show(int i) {
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(String...strs) {
System.out.println("show(String...strs)");
for(int i=0;i<strs.length;i++) {
System.out.println(strs[i]);
}
}
//编译不通过,不能与上一个方法同时存在
// public void show(String[]strs) {
// }
//编译不通过 说明:2.5
//The variable argument type String of the method
//show must be the last
// public void show(String...strs,int i) {
//
// }
3.调用时:
test.show(12);
test.show("hello");
test.show("hello","world");
test.show();//可以为0个
test.show("aa","bb","cc");
test.show(new String[] {"aa","bb","cc"});
Java的值传递机制
1.针对于方法内变量的赋值举例:
System.out.println("**********基本数据类型**********");
int m=10;
int n=m;
System.out.println("m="+ m + ",n="+n);
n=20;
System.out.println("m="+ m + ",n="+n);
System.out.println("**********引用数据类型*********");
Order o1=new Order();
o1.orderId=1001;
Order o2=o1;//赋值以后:o1和o2的地址值相同,都指向了堆空间中同一个对象实体
System.out.println("o1.orderId="+o1.orderId+",o2.orderId="+o2.orderId);
o2.orderId=1002;
System.out.println("o1.orderId="+o1.orderId+",o2.orderId="+o2.orderId);
}
class Order{
int orderId;
}
规则:
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
2.针对于方法的参数概念
形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
3.Java中参数传递机制:值传递
规则:
如果参数是基本数据类型,此时实参赋给形参的是,实参真是存储的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
推广:
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
4.典型例题与内存解析:
例题1:
例题2:
递归方法
1.定义
递归方法:一个方法体调用它自身
2.如何理解递归方法?
方法递归包含了一种隐式循环,它会重复执行某段代码,但这种重复执行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
3.举例:
//例1:计算1-100之间所有的自然数的和
//方式一:
// int sum=0;
// for(int i=1;i<=100;i++) {
// sum+=i;
// }
RecursionTest test=new RecursionTest() ;
System.out.println(test.getSum(100));
System.out.println(test.getSum1(2));
System.out.println("***************************");
int value=test.f(10);
System.out.println(value);
}
//方式二:计算1-n之间所有自然数的和
public int getSum(int n) {
if(n==1) {
return 1;
}else {
return n+getSum(n-1);
}
}
//例2:计算1-n之间所有自然数的乘积
public int getSum1(int n) {
if(n==1) {
return 1;
}else {
return n*getSum1(n-1);
}
}
//例3:已知有一个数列:f(0)=1,f(1)=4,f(n+2)=2*f(n-1)+f(n),
//其中n是大于0的整数,求f(10)的值。
public int f(int n) {
if(n==0) {
return 1;
}else if(n==1) {
return 4;
}else {
return 2*f(n-1)+f(n-2);
}
}
//例4:输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值
//例5:汉诺塔问题
//例6:快排
标签:JAVA,形参,int,数据类型,面向对象,对象,方法,public
From: https://www.cnblogs.com/nebun/p/16656626.html