Java(八)

知识点1:可变形参的方法(jdk5.0新特性)

package com.atguigu.java;

/**
 * 
 *
 * 测试java中方法的可变形参的使用(jdk5.0的新特性)
 *
 * 1. 可变形参的格式:数据类型 ... 参数名
 * 2. 在调用可变形参的方式时,可以给可变形参赋值的参数个数为:0个,1个,2个,....
 * 3. 可变形参的方法与同一个类中,相同方法名的多个方法间构成重载。(除了第4点中的情况)
 * 4. 可变形参的方法a与 参数同类型的数组的形参的方法b 不能在一个类中同时声明。
 * 5. 可变形参要求必须声明在方法的形参的最后。
 * 6. 一个方法的形参位置最多只能声明一个可变形参。
 *
 */
public class ArgsTest {
    public static void main(String[] args) {
        ArgsTest test = new ArgsTest();
        test.sum(3);
        test.sum(3,4);
        test.sum();

//        test.sum(new int[]{1,2,3,4,5});

        test.sum(1,2,3,4,5);
    }

    public void sum(int i,int j){
        System.out.println( i + j);
    }

    public void sum(int i){
        System.out.println(i * i);
    }

    public void sum(int ... arr){
        System.out.println("可变形参的方法");
        for(int i = 0;i < arr.length;i++){
            System.out.println(arr[i]);
        }
    }
    //与上一个方法不能同时存在
//    public void sum(int[] arr){
//        for(int i = 0;i < arr.length;i++){
//            System.out.println(arr[i]);
//        }
//    }

    public void sum(String s,int ... arr){

    }
}

知识点2:方法的参数传递机制:值传递(重点、难点)

1. 方法内变量的传递

package com.atguigu.java;

/**
 *
 * 变量间的传递规则:
 *
 *  基本数据类型:将基本数据类型变量保存的数据值传递过去。
 *
 *  引用数据类型:将引用数据类型变量保存的对象(或数组)地址值传递过去。
 *
 */
public class VariableTansferTest {

    public static void main(String[] args) {

        int m = 10;
        //主要看这:
        int n = m;

        System.out.println("m = " + m);
        System.out.println("n = " + n);

        m = 20;
        System.out.println("m = " + m);
        System.out.println("n = " + n);

        System.out.println("#######################");

        Order o1 = new Order();
        o1.orderId = 1001;
        System.out.println(o1.orderId);//1001
        //主要看这:
        Order o2 = o1;

        System.out.println(o1);
        System.out.println(o2);

        o2.orderId = 1002;
        System.out.println(o1.orderId);//1002

    }

}

class Order{
    int orderId;
}

2. 方法参数的传递机制

/**
 *
 * 1. 形参:方法声明时,小括号内声明的参数
 *    实参:方法调用时,实际传递过去的参数
 *
 *
 * 2. 方法的参数传递机制:值传递机制
 *    对于基本数据类型来讲,传递的是基本数据类型变量保存的数据值。
 *    对于引用数据类型来讲,传递的是引用数据类型变量保存的地址值。
 *
 */
  • 代码举例1
public class ValueTransferTest1 {
    public static void main(String[] args) {
        int m = 10;
        int n = 20;
        System.out.println("m = " + m);
        System.out.println("n = " + n);

        //交换两个变量的值
//        int temp = m;
//        m = n;
//        n = temp;

        //调用方法,实现变量的交换:No
        ValueTransferTest1 test = new ValueTransferTest1();
        test.swap(m,n);

        System.out.println("m = " + m);
        System.out.println("n = " + n);
    }

    public void swap(int m,int n){
        int temp = m;
        m = n;
        n = temp;
    }
}

对应的图示:

在这里插入图片描述

  • 代码举例2
public class ValueTransferTest2 {

    public static void main(String[] args) {
        Data data = new Data();
        data.m = 10;
        data.n = 20;

        System.out.println("m = " + data.m + ", n = " + data.n);

        ValueTransferTest2 test = new ValueTransferTest2();

        //交换两个变量的值:yes!
        test.swap(data);
        //思考:是否可以交换m和n:NO!
//        test.swap(data.m,data.n);
        System.out.println("m = " + data.m + ", n = " + data.n);
    }

    public void swap(int m,int n){
        int temp = m;
        m = n;
        n = temp;
    }

    public void swap(Data  data){
        int temp = data.m;
        data.m = data.n;
        data.n = temp;
    }
}


class Data{
    int m;
    int n;
}

对应的图示:

在这里插入图片描述

  • 练习1:

在这里插入图片描述

对应的内存结构:

在这里插入图片描述

  • 练习2:见《补充:对象数组》

知识点3:递归方法

/**
 *
 * 递归方法:一个方法体内调用它自身。
 * 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
 * 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
 */
public class RecurionTest {
    public static void main(String[] args) {
        RecurionTest test = new RecurionTest();
        System.out.println(test.getSum(100));
        System.out.println(test.getSum1(100));

        System.out.println(test.f(10));
    }

    //计算1-100自然数的和,并返回
    public int getSum(int num){
        int sum = 0;
        for(int i = 1;i <= num;i++){
            sum += i;
        }
        return sum;
    }

    //递归举例1:计算1-100自然数的和,并返回
    public int getSum1(int num){
        if(num == 1){
            return 1;
        }else{
            return num + getSum1(num - 1);
        }
    }

    //递归举例2:n!
    public int multiply(int num){
        if(num == 1){
            return 1;
        }else{
            return num * multiply(num - 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:已知一个数列:f(20) = 1,f(21) = 4,f(n+2) = 2*f(n+1)+f(n),
    //其中n是大于0的整数,求f(10)的值。
    public int func(int n){
        if(n == 20){
            return 1;
        }else if(n == 21){
            return 4;
        }else{
            return func(n + 2) - 2 * func(n + 1);
        }
    }

    //递归举例5:斐波那契数列(Fibonacci)
    //  1  1  2  3  5  8  13  21  34  55
    //  规律:一个数等于前两个数之和: f(n) = f(n - 1) + f(n - 2)

    //递归举例6:汉诺塔

    //递归举例7:遍历指定文件目录下的所有文件名
    public void printFileName(File dir){
        if(dir.isFile()){//是文件
            System.out.println(dir.getAbsolutePath());
        }else{//是文件目录
            File[] files = dir.listFiles();
            for(int i = 0;i < files.length;i++){
                printFileName(files[i]);
            }

        }
    }
    //拓展:计算指定文件目录的大小、删除指定的文件目录

    //递归举例8:快速排序
}

知识点4:面向对象的特征一:封装性

1. 封装性的引入

 /* 一、封装性的引入
 * 1.背景
 * 我们在创建了类的对象以后,可以通过"对象.属性"的方式给对象的属性赋值。此时,对象的属性的赋值需要满足相应
 * 的数据类型和取值范围。在此之外,实际问题中可能还有其他的一些限制条件。(比如:legs要求是正数、偶数、0~30)
 * 那么该如何添加限制条件呢?
 * 2. 给属性提供公共(public)的setXxx()方法用于设置属性的值。在方法内,可以添加额外的限制条件。
 *    给属性提供公共(public)的getXxx()方法用于获取属性的值。在方法内,可以添加额外的限制条件。
 *    同时,将类中的属性xxx,设置为私有的(private)
 */
public class AnimalTest {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        a1.name = "大黄";
//        a1.age = 5;
        a1.setAge(5);
//        a1.legs = -4;
        a1.setLegs(4);

//        System.out.println(a1.legs);
        System.out.println(a1.getLegs() + "!!!");

        a1.info();
        a1.eat();
//        a1.sleep();
    }
}

class Animal{//动物类
    //属性
    String name;
    private int age;
    private int legs;//腿的个数

    //方法
    //给legs属性赋值的方法
    public void setLegs(int l){
        if(l >= 0 && l % 2 == 0 && l <= 30){
            legs = l;
        }else{
            System.out.println("输入的数据不合法!");
        }
    }

    //获取legs属性值的方法
    public int getLegs(){
        return legs;
    }

    //提供关于age属性的set和get方法
    public void setAge(int a){
        age = a;
    }

    public int getAge(){
        return age;
    }


    public void eat(){
        System.out.println("动物进食");
        sleep();
    }

    private void sleep(){
        System.out.println("动物休息");
    }

    public void info(){
        System.out.println("name = " +name + ", age = " + age + ", legs = " +legs);
    }
}

2. 封装性的体现

/*二、封装性的体现:体现为4种不同的权限:(从小到大)private < 缺省 < protected < public
 * 体现之一:私有化类的属性,提供公共的get和set方法,用于获取和设置此属性的值。
 * 体现之二:私有化类的方法,表示此方法仅在类内部使用。不会暴露给类外使用
 * 体现之三:单例模式(涉及到私有化构造器)(后面讲)
 * 
 *  通过使用4种不同的权限修饰类及类的内部结构,从而体现被修饰的结构在调用时的可见性的大小!
 *
 * 三、4种不同的权限修饰符:private < 缺省 < protected < public
 *    > 4种不同的权限修饰符可以用来修饰类的内部结构:属性、方法、构造器、内部类。
 *    > 修饰类的话,仅能使用2种权限:缺省 、 public
 */

在这里插入图片描述

  • 便于理解

在这里插入图片描述

知识点5:类的成员之三:构造器

  • 理解
/**
 *
 * 测试类的成员之三:构造器(或构造方法、Constructor)
 *   Constructor:construct:构建、构造、建造、建设
 *
 *  1. 构造器的作用:①创建类的对象 ② 给对象的属性初始化赋值
 *
 *
 *  2. 说明:
 *  ① 如果没有显式声明类的构造器的话,则系统会默认提供一个空参的构造器。
 *  ② 构造器声明的格式:权限修饰符 类名(形参列表){}
 *  ③ 类中可以声明多个构造器,彼此之间构成重载。
 *  ④ 如果用户一旦显式声明了类的构造器,则系统不再提供参的构造器。
 *  ⑤ 类中一定会声明构造器。(自始至终都是对的)
 */
  • 代码举例
public class PersonTest {
    public static void main(String[] args) {
        Person p1 = new Person();

        Person p2 = new Person("Tom",12);
        p2.info();
    }
}

class Person{
    //属性
    String name;
    int age;

    //构造器
    public Person(){
        System.out.println("Person()....");
    }

    public Person(String n){
        name = n;
    }

    public Person(int a){
        age = a;
    }
    public Person(String n,int a){
        name = n;
        age = a;
    }
    //方法
    public void info(){
        System.out.println("name = " + name + ", age = " + age);
    }
    public void eat(){
        System.out.println("人吃饭");
    }
}

补充:对象数组

  • Student类
class Student {//学生类
    int number;//学号
    int state;//年级
    int score;//成绩

    public void info() {
        System.out.println("number : " + number +
                ", state : " + state + ", score : " + score);
    }

}
  • StudentUtil类
package com.atguigu.exer;

/**
 *
 * 将上课练习4:Student对象数组问题中涉及到的相关操作,封装进方法,测试执行。
 *
 * 比如:打印年级是3年级的方法;学生数组对象的排序;遍历Student数组中对象的方法
 */
public class StudentArrayTest {  //测试类
    public static void main(String[] args) {
        StudentArrayUtil util = new StudentArrayUtil();

        //创建学生数组
        Student[] stus = util.getStudentArray(20, 1, 6, 0, 100);

        //打印学生的基本信息
        util.printStudentArrayInfo(stus);

        //问题一:打印出3年级(state值为3)的学生信息。
        util.getStudentsInState(stus,3);

        //问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
        util.printStudentArray(stus,"descend");

        System.out.println("排序后:");
        //遍历
        util.printStudentArrayInfo(stus);

    }
}

class Student {//学生类
    int number;//学号
    int state;//年级
    int score;//成绩

    public void info() {
        System.out.println("number : " + number +
                ", state : " + state + ", score : " + score);
    }

}

/**
 * 操作Student数组的工具类
 */
class StudentArrayUtil{
    /**
     * 遍历学生数组元素的信息
     * @param stus
     */
    public void printStudentArrayInfo(Student[] stus){
        //打印学生的基本信息
        for (int i = 0; i < stus.length; i++) {
            Student s = stus[i];
            s.info();
        }
    }

    /**
     * 打印出指定年级的学生信息。
     * @param stus 学生数组
     * @param state 指定年级
     */
    public void getStudentsInState(Student[] stus,int state){
        for(int i = 0;i < stus.length;i++){
            if(stus[i].state == state){
                stus[i].info();
            }
        }
    }
//    public void printStudentArray(Student[] stus){
//        printStudentArray(stus,"ascend");
//    }
    /**
     * 使用冒泡排序按学生成绩排序,并遍历所有学生信息
     * @param stus
     */
    public void printStudentArray(Student[] stus,String sort){
        if("ascend".equals(sort)){//升序
            for (int i = 0; i < stus.length - 1; i++) {
                for (int j = 0; j < stus.length - 1 - i; j++) {
                    if (stus[j].score > stus[j + 1].score) {
                        swap(stus,j,j + 1);
//                        swap(stus[j],stus[j + 1]);
                    }
                }
            }
        }else if("descend".equals(sort)){//降序
            for (int i = 0; i < stus.length - 1; i++) {
                for (int j = 0; j < stus.length - 1 - i; j++) {
                    if (stus[j].score < stus[j + 1].score) {
                        swap(stus,j,j + 1);
//                        swap(stus[j],stus[j + 1]);
                    }
                }
            }
        }else{
            System.out.println("输入的排序方式有误!");
        }

    }

    /**
     * 交换stus数组中指定的index1和index2位置上的元素
     * @param stus
     * @param index1
     * @param index2
     */
    private void swap(Student[] stus,int index1,int index2){
        Student tempStudent = stus[index1];
        stus[index1] = stus[index2];
        stus[index2] = tempStudent;
    }

    //错误的写法
    public void swap(Student s1,Student s2){
        Student tempStudent = s1;
        s1 = s2;
        s2 = tempStudent;
    }

    /**
     * 返回学生数组
     * @param length
     * @param minState
     * @param maxState
     * @param minScore
     * @param maxScore
     * @return
     */
    public Student[] getStudentArray(int length,int minState,int maxState,int minScore,int maxScore){
        //1. 创建Student[]的数组,长度为length ---> 动态初始化
        Student[] stus = new Student[length];
        //2.通过循环,给每个数组元素赋值(即:创建对象)
        for (int i = 0; i < stus.length; i++) {
            stus[i] = new Student();
            //3. 给数组中的每个Student对象的属性赋值
            stus[i].number = i + 1;
            stus[i].state = (int) (Math.random() * (maxState - minState + 1) + minState); //[minState,maxState]
            stus[i].score = (int) (Math.random() * (maxScore - minScore + 1) + minScore);//[minScore,maxScore]

        }
        return stus;
    }
}
  • StudentTest测试类
/**
 *
 * 将上课练习4:Student对象数组问题中涉及到的相关操作,封装进方法,测试执行。
 *
 * 比如:打印年级是3年级的方法;学生数组对象的排序;遍历Student数组中对象的方法
 */
public class StudentArrayTest {  //测试类
    public static void main(String[] args) {
        StudentArrayUtil util = new StudentArrayUtil();

        //创建学生数组
        Student[] stus = util.getStudentArray(20, 1, 6, 0, 100);

        //打印学生的基本信息
        util.printStudentArrayInfo(stus);

        //问题一:打印出3年级(state值为3)的学生信息。
        util.getStudentsInState(stus,3);

        //问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
        util.printStudentArray(stus,"descend");

        System.out.println("排序后:");
        //遍历
        util.printStudentArrayInfo(stus);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值