基础5
方法
- 把程序中需要重复使用某段逻辑或者功能,提取出来形成一种新的形式—方法,也叫函数
- 定义格式
修饰符 返回值类型 方法名(参数列表){
方法体;
return 返回值;
}
// 写一个方法求1-n的和
// 明确结果:求1-n的和,那么和是一个整数,意味着结果是int类型,所以返回值类型也就是int类型
// 明确未知量:求1-n的和,n在方法中不能自动产生,需要使用方法的人来传入一个值,这个时候需要以参数形式来体现
// 定义方法的时候在()中定义了参数 --- 形式参数 - 形参
public static int sum(int n){
int sum = 0;
for(int i = 1; i <= n; i++){
sum += i;
}
return sum;
}
练习:哥德巴赫猜想 | 亲密数
- 哥德巴赫猜想:任何一个大于等于6的偶数都可以分解成两个质数之和。
16 = 3 + 13
16 = 5 + 11
输入大于等于6的偶数,然后输出它所有的分解形式
思路:在这个过程中要重复执行的代码是判断质数
import java.util.Scanner;
public class MethodExer1 {
public static void main(String[] args){
// 获取一个大于等于6的偶数
Scanner s = new Scanner(System.in);
int n = s.nextInt();
// 确保这个数字一定是合法的
while(n < 6 || n % 2 == 1){
n = s.nextInt();
}
for(int i = 3; i <= n / 2; i += 2){
if(isPrime(i) && isPrime(n - i))
System.out.println(n + "=" + i + "+" + (n - i));
}
}
public static boolean isPrime(int n){
for(int i = 2; i <= n / 2; i++){
if(n % i == 0)
return false;
}
return true;
}
}
- 亲密数:如果A的所有因子(含1而不含本身)之和等于B,而且B的所有因子(含1而不含本身)之和等于A,A和B就是一对亲密数
16:1+2+4+8 = 15
15:1+3+5 = 9
打印5000以内所有的亲密数
思路:需要重复执行的逻辑是获取一个数的所有因子之和
public class MethodExer2 {
public static void main(String[] args){
for(int a = 1; a <= 5000; a++){
// 获取a的所有因子之和
int b = sumAllFact(a);
// 获取b的所有因子之和
int i = sumAllFact(b);
// 判断b的所有因子之和是否为a
if(i == a && a < b)
System.out.println(a + "," + b);
}
}
// 求整数n的所有因子之和
public static int sumAllFact(int n){
int sum = 0;
// 获取这个数的所有的因子
for(int i = 1; i <= n / 2; i++){
if(n % i == 0)
sum += i;
}
return sum;
}
}
递归
目录,再往上一拉
注意:在递归的时候,当执行次数过多会产生StackOverflowError - 栈溢出错误
总结:在一些场景中,如果能确定这一项和前n项的关系,那么可以使用递归 —> 逆推
public class MethodDemo4 {
public static void main(String[] args){
System.out.println(add(100000));
}
//每次上一个或两个台阶,有多少种方式?n级台阶
public static int step(int n){
if(n == 1)
return 1;
if(n == 2)
return 2;
return step(n - 1) + step(n - 2);
}
public static int add(int n){
if(n == 1)
return 1;
// 求前n项的和(1---100的求和,而不是等差的求和)相当于求第n项加上前(n-1)项的和
// 在方法中调用了方法本身---递归
return n + add(n - 1);
}
public static long fac(int n){
//一个数的阶乘
if(n == 1)
return 1;
return n * fac(n - 1);
}
/*
public static int add(int n){
int sum = 0;
for(int i = n; i > 0; i--)
sum += i;
return sum;
}
*/
}
方法的重载
- 在同一个类中,存在了方法名一致而参数列表不同(参数个数不同或者是对应位置上的参数类型不同)的方法,方法的重载 — 依靠参数列表来区分调用的方法
- 方法在调用的时候会进行模糊匹配—参数类型在没有最符合的情况下会自动提升,就会导致提升之后可能会有多个匹配
public class MethodExer3 {
public static void main(String[] args){
// add(double, int) --- 参数进行类型的自动提升 --- add(double, double)
// System.out.println(add(3.5,3));
// add(int, int) -> add(int, double), add(double, int) -> add(double, double)
System.out.println(add(3,3));
}
public static double add(int i, double j){
// System.out.println("running~~~");
return i + j;
}
public static double add(double i, int j){
return i + j;
}
public static double add(double i, double j){
return i + j;
}
}
方法的传值
传递的是实际值
传递的是地址
- 方法是在栈内存中执行
- 方法在传值的时候,基本类型传递的实际值,数组传递的是地址。
- 传递地址之后,如果地址没有发生改变,则代码执行影响原来的数组;如果地址发生了改变,则改变之后的代码不会影响原来的数组
面向对象 vs 面向过程
- 面向过程在流程中关注动作执行的每一个细节 — 自己动手做
- 面向对象重点找这个对象,只要找到了对象,那么这个对象所具有的功能就能够被使用 — 找别人做
- 面向对象一定比面向过程好吗**?**— 不一定 —相对简单的事务建议使用面向过程,相对复杂的事务建议使用面向对象
- 面向对象本身是基于面向过程的
类与对象的关系
根据一类对象进行抽取和概括,将这类对象的特征抽取成了属性,将这类对象的行为抽取成了方法
对象的内存存储
成员变量和局部变量
- 定义位置:成员变量定义在类内方法外;局部变量是定义在方法或者是语句里面
- 作用范围:成员变量作用在整个类内;局部变量是只能作用在定义它的方法或者语句中
- 内存位置:成员变量随着对象的创建而存在了堆内存中并且在堆内存中赋予了默认值;局部变量在栈内存中存储
- 生命周期:成员变量再对象创建的时候出现,在对象被回收的时候销毁;局部变量在方法或者语句执行的时候创建,方法或者语句执行完成之后就立即销毁
小知识
- Eclipse(日食) — 免费、基于插件、开源、绿色 Kepler(开普勒) -> Luna(月神) -> Mars(火星) ->
Neon(霓虹灯) -> Oxygen(氧气)
https://blog.youkuaiyun.com/chenssy/article/details/12757911
https://vuejs.org/v2/guide/events.html?