方法的可变参数:
方法中有无参方法,有带参方法,都多个参数的方法;代码如下:
public class Dome { /* 方法无参和带参 */ public static void method() { System.out.println("我是一个无参的方法"); } public static void method(int a) { System.out.println("我是一个带参的方法"); } public static void method(int a,int b) { System.out.println("我是一个多参的方法"); } }
现在有一道题:定义一个方法,求2个数的和 和求多个数的和:我们的代码可以如下:
public class Dome01 { public static void main(String[] args) { System.out.println(sum(1, 2)); System.out.println(sum(1, 2, 9)); } /* 定义一个求和方法sum */ public static int sum(int a, int b) { int sum = 0; sum = a + b; return sum; } /* 定义多个求和方法sum */ public static int sum(int a, int b, int c) { int sum = 0; sum = a + b + c; return sum; } }
现在又有一个问题,如果我不知道我要求几个数的和,或者要求你写方法来求2个数,3个数,4个数,5个数,就这样一直下去,我们该怎么办,难道要一直的反复的写方法嘛,这样肯定是不现实的。所以java引入了可变参数。
可变参数的语法如下:
public class Dome02 { /* 可变参数的定义: */ public static void main(String[] args) { int sum = sum(1, 2); // 第一次调用两一参数的。 System.out.println(sum); int sum1 = sum(1, 2, 3); // 第二次调用三个参数 的。 System.out.println(sum1); } public static int sum(int... is) { // 可变参数的定义语法: 参数类型... 参数名 int sum = 0; for (int i = 0; i < is.length; i++) { sum = sum + is[i]; } return sum; } }
这样就可以完美的解决上面的那个问题了。
Object...obj :
这里过一下超类Object;obj是所有基本类型的超类,它包含所有的基本数据类型,如果把object当可变参数写会如何。演示如下:
public class Dome08 { public static void main(String[] args) { //可以看见我们传了所有的基本数据类型,还加了String这个引用类型 没有报错 obj("121",21,null,true,'a',1.2); } public static void obj(Object... objects) { /* 我们试着打印一下 */ for (int i = 0; i < objects.length; i++) { System.out.println(objects[i]); } } }
结果是什么呢,没错就是和你想象的一样:(将传入的所有类型数据都打印了出来)
注意点:
- 可变参数定义用三个点多一个少一个都不可以。
- 传参的数值必须和你所定义的类型相同,比如你定义了一个int...si 就不能传 String或其他比int类型大的。
- 也可以如这样定义:public static int sum(Stirng st, int... is){},可以和其他类型一起使用。
- 可变参数值的获取和数组一样,已下标的形式获取,比如你定义了 int...is并传了 1, 2两个数,则is[0] 就等于1,is[1]就等于2。
递归方法:
递归算法是一种算法,在java中递归就是指 一个方法自身调用自己,就称为递归。 由于递归是一种算法思想所以就直接按实例来展示。
案例01:n的阶乘
public class Dome03 { /* //简单介绍一下阶乘 * 一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。 * 自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。 * 亦即n!=1×2×3×...×(n-1)×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。 */ /* main入口 */ public static void main(String[] args) { int sum = sum(3); System.out.println(sum); } // 定义递归求阶乘方法 public static int sum(int n) { // n代表求几的阶乘 if (n == 1 || n == 0) { // 由于 0 的阶乘 是1 1 的阶乘也是1 所以设成出口 return 1; } else { return n * sum(n - 1); // 反复调用同一个方法直到碰上出口。 } } }
递归使用的注意点:
- 写递归算法一定要设置出口,否则会造成栈溢出;
- 递归方法的递归次数也不能太多,否则会造成栈溢出;
为什么会造成栈溢出? 因为,方法中的变量随着方法的调用而产生,随着方法消失而消失(且是在栈中开辟空间);递归是在方法中调用自己,所以当第一次执行的方法没有结束时,整个方法就不会被摧毁,所以空间就一直存在。然后在方法中再次调用方法就会重新开辟一个空间,反复调用,就会反复创建,但第一次的方法还没有执行完。导致方法无法摧毁,在创建的空间超过栈自身的内存而导致栈溢出。(死循环也这个样子)。
注:使用递归实现的功能,也可以用循环实现。
构造方法:
首先,我们需要知道的是每一个类都默认存在一个无参的构造方法。
构造方法的特点:
- 首先构造方法也是方法 同样也被权限修饰符所修饰
- 构造方法只有权限修饰符,与static 返回值无关,方法名必须与类名同名 ,不能被static、final、synchronized、abstract和native修饰
- 构造方法有 无参构造方法和带参构造方法
- 每一个类默认自带一个无参构造方法
构造方法的作用:
- 构造出一个类的实例,当new对象的时候,程序首先执行的就是构造方法。
- 对实例化进行初始化
- 构造方法可以进行重载
public class Dome04 { String name; int age; /* 无参构造方法 */ public Dome04() { //方法名为类名 } /* 带参构造方法 */ public Dome04(String name, int age) { //方法名为类名 且带着参数 } }
this,static关键字:
this关键字说明: this是java提供的关键字,用来表示自身实例化对象。
三种使用方法:
- this.属性名:用来访问本类的成员方法,区分成员变量和局部变量
- this.方法名:来访问本类中的方法,一般默认省略
- this()和this(参数1,参数2):来访问本类的构造方法,访问无参
this关键字演示代码如下:
public class Dome05 { String name; int age; /* this关键字演示 */ public static void main(String[] args) { this.name; //this关键字不能在静态方法中使用,main方法是一个静态方法。 } public Dome05() { this("zhangsan", 20); this.test1(); //this.方法名。访问 本类中的成员方法 } public Dome05(String name, int age) { this.name ="李四"; //this.属性名调用成员变量并赋值 this.age = age; //this.属性名区分成员变量的age和成员变量的age System.out.println(this.name); //this.name 调用成员变量name } public void test1() { System.out.println("我是一个成员方法"); } }
static关键字使用:static关键字是Java提供的,方便在没有创建对象的情况下进行调用(方法/变量)。static可以用来修饰类的成员方法、类的成员变量,另外也可以编写static代码块来优化程序性能。
- static静态修饰符可以修饰变量、方法、代码块、修饰的变量叫做静态变量,方法叫做静态方法,代码块叫做静态代码块
- 被静态修饰的,在类被加载的时候也一起加载。
静态变量被全局共享,且只有一个副本,在类初次加载的时候初始化。非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响;使用方法:static int i =0;
静态方法由于静态方法不依赖于任何对象就可以直接访问,因此对于静态方法来说,是没有this的;静态方法中不能访问非静态的成员变量
语法: static 返回值类型 方法名(参数列表){}
静态代码块 :
- 静态初始化块,用于类的初始化操作
- static代码块随着类的加载而加载,并且只初始化执行一次;
- 静态代码块在类内方法外,可以存在多个
- 静态初始化块中不能直接访问非static成员
代码演示如下:
public class Dome06 { /* static关键字的使用 */ static int a = 0; //静态的成员变量 int b = 1; static { System.out.println("我是一个静态代码块"); } public static void name() { //静态的成员方法 System.out.println(b); //静态成员方法不可以访问非静态成员变量 System.out.println("我是一个静态的成员方法"); } public void name2() { //普通的成员方法 System.out.println(a); //非静态成员方法可以访问静态成员变量 System.out.println("我是一个普通的成员方法"); } }
除去静态代码块之外,还有构造代码块,局部代码块 。如下:
public class Dome07 { //构造代码块:类中方法外,用{}括起,每次调用构造方法前执行,用于给对象进行初始化 { System.out.println("我是一个构造代码块"); } //静态代码块:类中方法外,加static修饰,用于给类进行初始化 static { System.out.println("我是一个静态代码块"); } public static void main(String[] args) { //局部位置,用于限定变量的生命周期,提高内存利用率。 { System.out.println("我是一个局部代码块"); } } }
单例模式:
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
-
1、单例类只能有一个实例。
-
2、单例类必须自己创建自己的唯一实例。
-
3、单例类必须给所有其他对象提供这一实例。
关键代码:构造函数是私有的。
代码实现:
1、懒汉式,线程不安全
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
2、饿汉式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
作业:
01.评委打分:
-
-
选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。
public class Dome03GameScore { /* * 在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。 选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 * (不考虑小数部分)。 */ public static void main(String[] args) { int[] arrysScore = arrysScore(); int avgScore = avgScore(arrysScore); System.out.println("这位选手的最终得分是:"+ avgScore); } // 键盘录入六位评委的打分 public static int[] arrysScore() { { System.out.println("录入程序开始"); } int[] arrys = new int[6]; Scanner sc = new Scanner(System.in); for (int i = 0; i < arrys.length; i++) { System.out.println("请输入第" + (i + 1) + "为评委老师的分数"); arrys[i] = sc.nextInt(); } return arrys; } // 求六个评委的分数最大值 public static int maxScore(int[] arrsys) { int temp = arrsys[0]; for (int i = 0; i < arrsys.length-1; i++) { if (arrsys[i] < arrsys[i + 1]) { temp = arrsys[i + 1]; } } return temp; } // 求六个评委的分数最小值 public static int minScore(int[] arrsys) { int temp = arrsys[0]; for (int i = 0; i < arrsys.length-1; i++) { if (arrsys[i] > arrsys[i + 1]) { temp = arrsys[i + 1]; } } return temp; } // 求评委分数的平均值(去掉最大值最小值的平均值) public static int avgScore(int[] arrys) { int avg = 0; for (int i = 0; i < arrys.length; i++) { if (arrys[i] == maxScore(arrys) || arrys[i] == minScore(arrys)) { continue; } else { avg = avg + arrys[i]; } } return avg / (arrys.length - 2); } }
02.有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13....求出这个数列的前20项之和。
public class Dome03 { public static void main(String[] args) { /* 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13....求出这个数列的前20项之和。 */ // 方式一:for循环 double a = 2.0, b = 1.0, sum = 0; for (int i = 1; i < 20; i++) { double tem = 0; sum = sum + a / b; tem = a; a = a + b; b = tem; } // 方式二 递归 System.out.println(sum); double sumScore = sumScore(2, 1); System.out.println(sumScore); } // 方式二 递归 static double i = 1; static double temp = 0; static double sum = 0; public static double sumScore(double a, double b) {// 传递a b初始值 a=2,b=1 2/1;求和的值sum if (i < 20 && i >= 1) { sum = sum + a / b; /* System.out.println(sum); */ temp = a; a = a + b; b = temp; i++; return sumScore(a, b); } else { return sum; } } }
个人学习,内容简略