面向对象
“万事万物皆对象”
- 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
- 涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。
内存解析的说明
- 引用类型的变量,只能存储两类值 null 或 地址值
class Phone{
double price;//价格
}
public class PhoneTest {
public static void main(String[] args) {
Phone p = new Phone();
System.out.println(p);//Phone@15db9742(包含类名)
Phone p2 = null; // 可以被null赋值
}
}
匿名对象的使用
- 定义:创建的对象,没有被显示赋值变量名
- 特征:只能使用一次
public class Phone {
double price;
//发送邮件
public void sendEMail(){
System.out.println("发送邮件");
}
}
public class PhoneTest {
public static void main(String[] args) {
new Phone().sendEMail();
}
}
- 常用用法
public class Phone {
double price;
public void writeEMail(){
System.out.println("编写邮件");
}
public void sendEMail(){
System.out.println("发送邮件");
}
}
class PhoneMall{
//将众多方法编写到一个方法中,实现通过一个匿名对象执行多个方法
public void makeEMail(Phone phone){
phone.writeEMail();
phone.sendEMail();
}
}
public class PhoneTest {
public static void main(String[] args) {
//使用匿名对象调用方法
new PhoneMall().makeEMail(new Phone());
}
}
方法重载
- 定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表(参数个数或类型)不同即可。
- 举例:如下的4个方法构成了重载
class overLoading{
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");}
}
-
判断是否重载
- 同一个类,同名方法,参数个数不同或者参数类型不同
- 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
-
重载的自动类型提升
- 若输入为数值型,当有类型全吻合的情况下,直接匹配该方法
- 若输入为数值型,若没有类型全吻合的情况下,提升数据类型,再匹配,若未果,再提升数据类型,直至Double
- 若数据类型提升后匹配无果,再匹配包含参数个数可变类型的方法
可变个数参数
- 可变个数形参的格式:数据类型 … 变量名
- 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
- 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
- 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
- 可变个数形参在方法的形参中,必须声明在末尾
- 可变个数形参在方法的形参中,最多只能声明一个可变形参。
示例:
public void show(String strs){
System.out.println("1");
}
// 可变参数类型可以构成重载
public void show(String ... strs){
System.out.println("2");
}
// 不能和上一个方法同时存在
// public void show(String[] strs){
//
// }
值传递机制
- 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
- 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
System.out.println("***********基本数据类型:****************");
int m = 10;
int n = m; //将m的值赋给n
System.out.println("m = " + m + ", n = " + n); // m 10 n 10
n = 20; //修改n的数值
System.out.println("m = " + m + ", n = " + n);// m 10 n 20
System.out.println("***********引用数据类型:****************");
Order o1 = new Order();
o1.orderId = 1001;
Order o2 = o1;//赋值以后,o1和o2的地址值相同,都指向了堆空间中同一个对象实体。
// o1 1001 o2 1001
System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);
o2.orderId = 1002;
// o1 1002 o2 1002
System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);
- 形参:方法定义时,声明的小括号内的参数
- 实参:方法调用时,实际传递给形参的数据
- 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
- 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
public class ValueTransferTest1 {
public static void main(String[] args) {
int m = 10;
int n = 20;
System.out.println("m = " + m + ", n = " + n);
//交换两个变量的值的操作
// int temp = m ;
// m = n;
// n = temp;
ValueTransferTest1 test = new ValueTransferTest1();
//调用方法交换两数的数据
test.swap(m, n);
//发现调换失败
System.out.println("m = " + m + ", n = " + n);
}
public void swap(int m,int n){
int temp = m ;
m = n;
n = temp;
}
}
引用数据类型内存解析:
当 swap 方法 调用时,因为传递的是基本数据类型,则 main中的(m 和 n)将数值赋值给swap 中的(m,n)
此时栈空间 有 main(m,n) 和 swap(m,n)
而此时开始交换数据,交换过程过后,swap中的(m,n)数值进行了交换,但是main(m,n)没有进行交换。
方法执行过后
swap(m,n)出栈。内存中只剩下了 main(m,n),输出发现,俩者的值没有发生交换
若想交换m,n的值,需把传递的类型更改为引用数据类型
class Data{
int m;
int n;
}
public class DateTest {
public static void main(String[] args) {
//新建一个Date对象,准备作为参数传给test
Data data = new Data();
data.m = 10;
data.n = 20;
System.out.println("m = " + data.m + ", n = " + data.n);
//新建test对象,执行swap方法
DateTest test = new DateTest();
// 传递参数为引用参数类型
test.swap(data);
//数值进行了交换
System.out.println("m = " + data.m + ", n = " + data.n);
}
public void swap(Data data){
int temp = data.m;
data.m = data.n;
data.n = temp;
}
}
递归
1.递归方法:一个方法体内调用它自身。
2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
3. 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
例1: 计算1-n之间所有自然数的和
public class Recursion {
//计算1-n之间所有自然数的和
public static int getSum(int a){
if ( a == 1){
return 1;
}else{
return a + getSum(a-1);
}
}
}
public class RecursionTest {
public void main(String[] args) {
Recursion r1 = new Recursion();
int sum = r1.getSum(100);
System.out.println(sum);
}
}
例2:计算1-n之间所有自然数的乘积:n!
public class Recursion {
//计算1-n之间所有自然数的和
public int getSum(int a){
if ( a == 1){
return 1;
}else{
return a * getSum(a-1); //修改此处为乘法
}
}
}
public class RecursionTest {
public static void main(String[] args) {
Recursion r1 = new Recursion();
int sum = r1.getSum(100);
System.out.println(sum);
}
}
例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
其中n是大于0的整数,求f(10)的值。
//例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
//其中n是大于0的整数,求f(10)的值。
public class Function {
public int getNum(int a){
if (a == 0){
return 1;
}else if (a == 1){
return 4;
}else{
return (2 * getNum(a-1) + getNum(a-2));
}
}
}
public class FunctionTest {
public static void main(String[] args) {
Function test = new Function();
int result = test.getNum(10);
System.out.println(result);
}
}
例4:斐波那契数列
指的是这样一个数列:1、1、2、3、5、8、13、21、34…
public class Fibonacci {
public int getResult(int a){
if (a == 1){
return 1;
}else if (a == 2){
return 1;
}else{
return (getResult(a-1) + getResult(a-2));
}
}
}
public class FibonacciTest {
public static void main(String[] args) {
Fibonacci test = new Fibonacci();
int result = test.getResult(10);
System.out.println(result);
}
}
例5:汉诺塔问题
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
数列 1 3 7 15 31 …
public class Hannover {
public int getResult(int a){
if (a == 1){
return 1;
}else{
return (2*(a-1) + 1);
}
}
}
public class HannoverTest {
public static void main(String[] args) {
Hannover test = new Hannover();
int result = test.getResult(10);
System.out.println(result);
}
}
//例6:快排
练习题
定义一个类PassObject,在类中定义一个方法printAreas(),
该方法的定义如下:public void printAreas(Circle c, int time)
在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积。
例如,time为5,则输出半径1,2,3,4,5,以及对应的圆面积。
在main方法中调用printAreas()方法,调用完毕后输出当前半径值。
public class Circle {
double radius;
public double getArea(){
return Math.PI * radius * radius;
}
}
public class PassObject {
public void printAreas(Circle c, int time){
for (int i = 0;i < time ; i++){
c.radius = i;
double area = c.getArea();
System.out.println("半径为"+i+"的圆的面积为"+area);
};
}
}
public class PassObjectTest {
public static void main(String[] args) {
PassObject test = new PassObject();
Circle c = new Circle();
test.printAreas(c, 10);
}
}