递归解决问题的思想及简单的问题
Java中的递归形式
在Java中递归就是在方法中调用方法的现象;
递归的基本思想
递归方法体现的思想是一种先拆分后合并的思想,对于问题的解决,我们可以先将问题拆分成小问题,当然这种小问题是我们可以解决的,当我们的到小问题的答案后,我们再将每个答案合并起来,最终实现大的问题得以解决,当然这样讲是很粗糙的理论,我们还是通过简单的例子来进行理解;
例如我们现在要实现一个6的阶乘:
我们都知道6!=6 * 5 * 4 * 3 * 2 *1,但现在我们需要用递归的思想来解决这个问题,我要你直接给我6!的值,很明显大多数人不可能直接知道6!的值,那么我们就可以对这个问题进行拆分6! = 5! * 6;那么问题又来了,我们也不能直接知道5!的值是多少;所以我们需要对这个问题再进行拆分5!=4!*5;当然4!我们不能直接给出答案;所以我们继续进行拆分4!=3!*4;再拆分3!=2!*3;再拆分2!=1!2;这个时候,1!的阶乘就是一个很小很小的问题了,我们都知道1!=1,这个时侯,我们就知道了2!=21;以此类推,最终我们就能得到6!的值,当然当我你看完这一大堆,你或许会觉得我在画蛇添足,我直接根据阶乘计算方式计算值不就行了,但这个拆分合并的 过程体现的就是递归的思想,有很多问题并不是我们直接就知道它的计算公式的,在解决问题时,递归就是一种很好的解决思想,我们可以在以后常用这种思想;
代码实现:
public class MyTest2 {
public static void main(String[] args) {
//求 5的阶乘
//用递归来做
int r= jieCheng(6);
System.out.println("结果是"+r);
}
private static int jieCheng(int i) {
if(i==1){
return 1;
}else{
return i*jieCheng(i-1);
}
}
}
可见我们在方法jieCheng()中又调用了方法jieCheng()最终当i=1时将1返回继而求出6!的值;
用递归方法解决不死神兔问题
需求:兔子问题(斐波那契数列)
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 …
代码实现:
public class jiecheng{
public static void main(String[] args) {
int sum = sumRabbit(20);
System.out.println("兔子的对数" + sum);
}
private static int sumRabbit(int i) {
if (i == 1 || i == 2) {
return 1;
} else {
return sumRabbit(i - 1) + sumRabbit(i - 2);
}
}
}
输出结果:
面向对象的基本理论知识
这部分可以说时Java的重重之重了,我们一开始就讲过,Java语言是一种面向对象的语言,它与面向过程的语言不同就是它操作的是对象,我们只关心对象要做什么,而不用管怎么做,怎么做是类方法中需要去设计的逻辑,我们创建对象,用对象来调用方法,实现相应的功能即可;
面向对象的思想特点
是一种更符合我们思想习惯的思想
可以将复杂的事情简单化
将我们从执行者变成了指挥者,角色发生了转换
面向对象的特征
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
类与对象的概述
类是一个抽象的概念,而对象是具体的,它们两个的关系我们可以这样子理解;人类,植物类是指两个不同的类,而小明和牵牛花指的就是两种类里不同的对象,两个对象都可以做一些 事情;也就是说类就是多个对象的基本特征的和特征方法的集合,它不确定是那种具体特征,例如小明的姓名,性别,年龄等,而小明的行为就是该类的类方法;我们学习的Java语言最基本单位是类,所以,我们就应该把事物用一个类来体现。
由此我们就得到了现实中的事物和类的对应关系
事物 类
属性 ----------------- 成员变量
行为 ----------------- 成员方法
定义类其实就是定义类的成员(成员变量和成员方法)
成员变量 和以前定义变量是一样的,只不过位置发生了改变。在类中,方法外。
成员方法 和以前定义方法是一样的,只不过把static去掉,因为static是一个权限修饰符,它可以修饰类中的成员变量和成员方法,它表示的是私有的,被static修饰的成员变量和方法只能在本类中调用不能被其他的类调用;我们定义成员方法如果使用了static修饰符的话,我们创建的对象就不能调用类中的成员方法了,那么我们定义的成员方法将没有意义;
接下来我们来进行创建一个学生的类其中包含成员变量和成员方法,然后建立一个对象小明来进行类的测试
代码:
students类的创建
public class students {
char sex='男';
int age=21;
String name="小明";
//上面三个是我定义的三个成员变量
public void introduce(){
System.out.println("小明说我今年" + age + "岁了");
}
}
小明对象的创建以及查看成员变量和使用成员方法:
public class xiaoming {
public static void main(String[] args) {
students xiaoming = new students();
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(xiaoming.sex);
xiaoming.introduce();
}
}
运行结果是:
在这里我们需要注意一个问题,就是成员变量和局部变量的区别:
A:在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上(形参)
B:在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
C:生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:: 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
还有一个需要注意的点是
方法的形式参数是类名的时候该如何处理
Java中参数传递问题
形式参数
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
方法的参数是类名
如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
这里我们来看一个范例来理解:
package com.classs.test;
public class xiaoming {
public static void main(String[] args) {
students xiaoming = new students();
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(xiaoming.sex);
xiaoming.introduce(xiaoming,xiaoming.age);
System.out.println(xiaoming.age);
}
public static class students {
char sex='男';
int age=21;
String name="小明";
//上面三个是我定义的三个成员变量
public void introduce(students xiaoming ,int age){
age=54;
System.out.println("小明说我今年" + age + "岁了");
System.out.println(xiaoming.age);
}
}
}
传入方法的age,即使在方法中我们对其值进行了更改但对于对象引用的数据仍未发生变化,这是因为我们在操作方法时,我们是在栈内存中对形式参数进行操作,而建立新对象的成员变量存在于对内存之中,我们没有对其进行操作,所以其值不改变。
匿名对象的调用匿名对象
匿名对象就是没有名字的对象
匿名对象应用场景
a:调用方法,仅仅只调用一次的时候。
b:匿名对象可以作为实际参数传递。
例如: new students()
这就是我们定义了一个匿名对象;
this关键字的概述及其应用
A:为什么要有this
当我们的局部变量和成员变量相同的时候,如果我们不使用this关键字,那么会导致一个问题:就是局部变量隐藏了成员变量的问题
B:this关键字特点
是当前类的对象引用。
简单的记,它就代表当前类的一个对象。谁调用这个方法,那么该方法的内部的this就代表谁
C:this的应用场景
解决局部变量隐藏成员变量
this的使用主要在类的构建过程中,对有的成员变量和局部变量重名的时候,局部变量会隐藏成员变量的时候,用this来表明成员变量。
最后我们来实现一个案例
在用户购买电脑时,先给顾客展现一个机型的价格和配置,当用户提出预算价格时给用户推荐价格接近预算的款式并在控制台展示
代码:
类模块
package method;
import java.util.Scanner;
public class compute {
private int screen;
private String coulur;
private double price;
public compute(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
private String brand;
public int getScreen() {
return screen;
}
public void setScreen(int screen) {
this.screen = screen;
}
public String getCoulur() {
return coulur;
}
public void setCoulur(String coulur) {
this.coulur = coulur;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public compute() {
}
public compute(int screen, String coulur, double price) {
this.screen = screen;
this.coulur = coulur;
this.price = price;
}
public void diaoyong(){
jisuan();
}
private void jisuan(){
System.out.println("请规定输入你可以接受的价格,我们将为你推荐适合价格的款式");
Scanner jc=new Scanner(System.in);
int x=jc.nextInt();
String [] a={"华硕S1","华硕s2","华硕s3"};
int [] b={2500,3500,4500};
int [] c={1080,1080,720};
String []d={"备选颜色:red,black,bulu","备选颜色:red,white,yellow","备选颜色:green,red,black"};
int[]p=new int [3];
int i ;
for (i = 0; i <3 ; i++) {
p[i]=b[i]-x;
if(p[i]<0){p[i]=-p[i];}
}
int min=p[0];
for (int j = 0; j < 3; j++) {
min = min <p[j]?min:p[j];
}
System.out.println("推荐的款式有");
for (int k = 0; k <3; k++) {
if(min==p[k]) {
System.out.println(a[k]);
System.out.println(b[k]);
System.out.println(c[k]);
System.out.println(d[k]);
}
}
}
对象模块
package method;
public class auas {
public static void main(String[] args) {
compute auas=new compute();
auas.setBrand("华硕");
auas.setCoulur("black");
auas.setPrice(5200);
auas.setScreen(1082);
System.out.println(auas.getBrand());
System.out.println(auas.getCoulur());
System.out.println(auas.getScreen());
System.out.println(auas.getPrice());
auas.diaoyong();
}
}
输出结果:
很明显如果我们只对对象进行操作,无论时代码量还是逻辑,都简单很多,这就有助于我们完成更多更复杂的工作量,相比面向过程语言我们的优势是很大的;