zoukankan      html  css  js  c++  java
  • 疯狂Java学习笔记(008)

    回顾

    一、数组

    1.数组的概念:

      同种数据类型若干个数值的组合.称为数组.

      实际上就是多个内存空间(变量)的组合.

      数组的元素值可以在数据类型的表数范围内发生变化!!! 

    2.数组的元素:

      element:数组中的数值就称为数组的元素!

    3.数组的长度:

      length:就是数组中元素的个数.

    4.元素的索引:

      index:数组中元素的编号.从0开始.最大值是数组的长度-1.

    5.数组的初始化方式:

      初始化指的是数组中的元素第一次赋值,以后再赋值就不是初始化.

      1.> 动态初始化:只指定数组的长度.由系统赋默认初始值(0/0.0/false/null).

        int[] arr = new int[5];

        在堆空间中开辟5个能存放int型数据的空间,赋予默认的初始值,并把地址值返回给变量arr.

      2.静态初始化:在定义数组时指定数组的初始化值.此时不能指定数组的长度!(静态和动态不能同时使用!!)

        int[] arr = new int[]{1,2,3};

        //在堆空间中开辟3个存放int型数据的空间,把1,2,3放进去,然后把内存地址值返回给变量arr.

        简化写法:

        int[] arr = {1,2,3};

    5. 数组类型的变量直接打印的结果:

      以int型数组为例:

      [I@xxxx

      [ :指的是变量中保存的内存空间是数组类型

      I :指的是数组的类型是int型(也就是数组元素的类型)

      @ :固定的分隔符

      xxxx :一串字符串,十六进制.由内存地址计算而来的.

      用途:比较两个数组是否是同一个数组!!(内存地址值相同,肯定是同一个数组)

    二、jvm内存结构:

    1.栈:

        凡是方法中定义的变量(包括方法的形参)都是在栈中.

        栈中的变量没有初始化值,使用之前必须手动赋值.

        方法执行,变量就存在,方法执行完,变量所占用的空间自动释放!

    2.堆:

        凡是使用new关键字创建出来的对象都是在堆中!

        堆中的变量都有初始化值:(0/0.0/false/null)

        堆中的变量随着对象的存在而存在.当对象没有任何引用指向它时,它所占用的空间由垃圾回收器负责回收. 

    3.方法区:

        .class字节码文件和方法定义

        System

        Scanner

        Math

    4.本地方法栈:

    5.程序计数器:

    三、数组的遍历:traversal

      依次访问数组中每个元素的一种机制!

      使用循环(循环的是元素的索引)就可以遍历每个元素!

      循环的顺序:从前往后,从后往前.

      ***数组操作的两个常见异常:

      1.ArrayIndexOutOfBoundsException

        索引超出了正常值[0,数组的长度-1]范围:

      2.NullPointerException

        一个数组变量,被赋予了null值,使用它去访问数组中的元素,发生空指针异常.

    作业:

    1.数组初始化的两种格式:

    2.什么是数组的遍历?

    3.jvm虚拟机的内存划分成几个区域,各个区域中的变量都有什么特点?

    4.定义一个方法,用于将一个int数组的偶数索引的元素抽取(extract)出来.

    /*
    
        定义一个方法,用于将一个int数组的偶数索引的元素抽取出来.
        计算偶数索引元素的个数,创建新的数组,
        遍历源数组,判断符合条件的,赋值给新数组
        
    */
    public class ExtractEvenIndexDemo{
        public static void main(String[] args){
            int[] arr = {1,2,3,4,5,6,7,8,9,0};
            int[] dest = extractEvenIndex(arr);
            printArray(dest);
        }
        
        public static void printArray(int[] arr){
            for(int i = 0;i<arr.length;i++){
                System.out.print(arr[i]);
                if(i != arr.length - 1){
                    System.out.print(",");
                }
            }
            System.out.println();
        }
        
        
        //返回值类型:int[]
        //形参列表:int[]
        public static int[] extractEvenIndex(int[] arr){
            //计算偶数索引的个数
            int[] dest = new int[(arr.length + 1) / 2];
            //遍历源数组,判断
            int index = 0;
            for(int i = 0;i<arr.length;i++){
                if(i % 2 == 0){
                    dest[index++] = arr[i];
                }
            }
            return dest;
        }
        
    }

    5.定义一个方法,用于将一个数组逆序.注意方法的返回值类型?即:逆序是否是产生了新的数组?

    /*
        5.定义一个方法,用于将一个数组逆序.注意方法的返回值类型?即:逆序是否是产生了新的数组?
        思路:
            并没有产生新的数组,而是把源数组中的元素逆序了!!
        重点:有多少次两两交换??
            4 -> 2
            5 -> 2
            6 -> 3
            7 -> 3
            ...
            
    */
    public class ReverseArrayDemo{
        public static void main(String[] args){
            int[] arr = {1,2,3,4,5,6,7};
            reverse(arr);
            printArray(arr);
            
        }
        
        public static void printArray(int[] arr){
            for(int i = 0;i<arr.length;i++){
                System.out.print(arr[i]);
                if(i != arr.length - 1){
                    System.out.print(",");
                }
            }
            System.out.println();
        }
        //没有返回值:void
        //形参列表:int[]
        public static void reverse(int[] arr){
            //计算两两交换的次数
            int count = arr.length / 2 ;
            //循环交换两个元素
            for(int i = 0;i<count;i++){
                //交换两个元素
                int temp = arr[i];
                arr[i] = arr[arr.length - 1 - i];
                arr[arr.length - 1 - i] = temp;
            }
            
        }
    }

    6.定义一个方法,用于将一个数组的所有元素变成它原来的元素和它前一个元素的和,(第一个元素除外!)

        即:若原数组为:[1,2,3,4,5]

        则方法执行后,数组变为:[1,3,5,7,9]

        注意:方法中不能创建新的数组!!!

    /*
        1.从前往后遍历:用临时变量保存当前要修改的元素的值,更改后面元素的时候,就可以使用原来元素的值.
        2.从后往前遍历!用元素的值和它前一个元素的和替换当前元素!
    */
    public class Demo1{
        public static void main(String[] args){
           int[] arr = {1,2,3,4,5};
           printArray(arr);
           // change1(arr);
           change2(arr);
           printArray(arr);
        }
        public static void printArray(int[] arr){
           for(int i = 0;i<arr.length;i++){
               System.out.print(arr[i]);
               if(i != arr.length - 1){
                  System.out.print(",");
               }
           }
           System.out.println();
        }
       
        //第二种方式:从后往前遍历
        public static void change2(int[] arr){
           //
           for(int i = arr.length - 1;i>0;i--){
               arr[i] = arr[i] + arr[i - 1];
           }
        }
       
        //第一种方式:使用临时变量保存上一次被覆盖的元素的值
        public static void change1(int[] arr){
           //定义一个变量,初始值为第一个元素的值.
           int temp = arr[0];
           for(int i = 1;i<arr.length;i++){
               //先把当前元素的值保留下来.
               int x = arr[i];
               //替换当前元素的值
               arr[i] = arr[i] + temp;
               //把当前元素原来的值,赋值给temp
               temp = x;
           }
        }
    }

    7.定义一个方法,用于模拟裁判打分的程序:一共有5个裁判打分,去掉一个最高分,去掉一个最低分.

    取剩余分数的平均值为最终的得分!!!注意:分数的数据类型!!!

    重点:自定义方法之间的互相调用!!!

    /*
    定义一个方法,用于模拟裁判打分的程序:一共有5个裁判打分,去掉一个最高分,去掉一个最低分.
    取剩余分数的平均值为最终的得分!!!注意:分数的数据类型!!!
     
    方法之间是互相调用的关系:
        自定义方法中可以使用jdk提供好的方法(比如打印方法),也可以调用自定义方法!!!
    */
    public class MarkDemo{
        public static void main(String[] args){
           int[] scores = {10,20,10,15,25};
           System.out.println("最终得分是: " + mark(scores));
        }
       
        //double
        //int[] scores
        public static double mark(int[] scores){
           //计算分数之和
           // System.out.println("abc");//自定义方法中调用jdk提供的方法
           int sum = getSum(scores);//自定义方法中调用自定义方法!!
          
           //减去最高分,最低分
           //求平均分返回
           return (sum - getMax(scores) - getMin(scores)) / 3.0;
        }
       
        //最高分(最大值)
        public static int getMax(int[] scores){
           int max = scores[0];
           for(int i = 1;i<scores.length;i++){
               if(scores[i] > max){
                  max = scores[i];
               }
           }
           return max;
        }
       
        //最低分(最小值)
        public static int getMin(int[] scores){
           int min = scores[0];
           for(int i = 1;i<scores.length;i++){
               if(scores[i] < min){
                  min = scores[i];
               }
           }
           return min;
        }
       
        //求数组所有元素之和
        public static int getSum(int[] scores){
           //定义变量,初始值为0
           int sum = 0;
           for(int i = 0;i<scores.length;i++){
               sum += scores[i];
           }
           return sum;
        }
    }

    8.定义一个方法,用于取出一个数组中所有偶数元素组成的数组!

    /*
        定义一个方法,用于取出一个数组中所有偶数元素组成的数组!
        首先计算偶数元素的个数,用个数创建一个新的数组,
        遍历源数组,把符合条件的元素赋值给新数组
       
        两次遍历:
           1.求偶数元素的个数
           2.赋值
    */
    public class ExtractEvenElementDemo{
        public static void main(String[] args){
           int[] src = {1,2,3,4,5,6,67,7,8};
           printArray(src);
          
           int[] dest = extractEvenElement(src);
          
           printArray(dest);
        }
        public static void printArray(int[] arr){
           for(int i = 0;i<arr.length;i++){
               System.out.print(arr[i]);
               if(i != arr.length - 1){
                  System.out.print(",");
               }
           }
           System.out.println();
        }
       
        //返回值类型:int[]
        //形参列表:int[] src
        public static int[] extractEvenElement(int[] src){
           //第一次遍历,求偶数元素的个数
           int len = 0;
           for(int i = 0;i<src.length;i++){
               if(src[i] % 2 == 0){
                  len++;
               }
            }
          
           //创建新数组
           int[] dest = new int[len];
           //第一次遍历,求偶数元素的个数
           int index = 0;
           for(int i = 0;i<src.length;i++){
               if(src[i] % 2 == 0){
                  dest[index++] = src[i];
               }
           }
           return dest;
        }
    }
     

    9.定义一个方法,用于取出一个数组中指定索引范围的元素组成的数组!!

        例如:可以取出一个数组第2个到第5个索引组成的数组!

     
    /*
    定义一个方法,用于取出一个数组中指定索引范围的元素组成的数组!!
        例如:可以取出一个数组第2个到第5个索引组成的数组!
    思路:
        根据传递进来的两个数,确定要截取的范围:
        用这个范围的长度去创建一个新数组,
        遍历源数组,赋值!
       
    */
    public class GetArrayDemo{
        public static void main(String[] args){
           int[] arr = {1,2,3,4,5,6,7,8,9,0};
           int[] dest = getArray(arr,2,5);
           printArray(dest);
        }
       
        public static void printArray(int[] arr){
           for(int i = 0;i<arr.length;i++){
               System.out.print(arr[i]);
               if(i != arr.length - 1){
                  System.out.print(",");
               }
           }
           System.out.println();
        }
       
        //int[]
        //int[] arr,int start,int end
        public static int[] getArray(int[] arr,int start,int end){
           //计算目标元素的个数
           int len = end - start + 1;
           //创建新数组
           int[] dest = new int[len];
           //遍历源数组赋值
           int index = 0;
           for(int i = start;i<=end;i++){
               dest[index++] = arr[i];
           }
           //
           return dest;
        }
    }
     
     

    选作题:

    用数组实现:产生一个有5个范围在(1-100)之间的随机数元素的数组,要求元素不能重复!!!

    /*
    选作题:
    用数组实现:产生一个有5个范围在(1-100)之间的随机数元素的数组,要求元素不能重复!!!
    思路:
        先产生一个有默认值的数组,
        遍历,每次都产生一个随机数,拿这个随机数到数组中判断
           如果已经存在,就再次产生一个随机数,再次进行判断
           如果不存在,就直接给当前的元素赋值!
    */
    public class GetRandomArrayDemo{
        public static void main(String[] args){
           int[] arr = new int[5];//0
          
           //遍历数组,产生随机数,判断,符合条件再对元素赋值
           for(int i = 0;i<arr.length;i++){
               int r = (int)(Math.random() * 100);
               //判断是否已经在数组中!
               /*
               while(exists(arr,r)){ //true ,表明已经存在,再次产生一个新的随机值!
                  r = (int)(Math.random() * 100) + 1;
               }
               */
               //优化后的方法,需要三个参数,第二个参数表明比较的范围
               while(exists2(arr,i,r)){ //true ,表明已经存在,再次产生一个新的随机值!
                  r = (int)(Math.random() * 100);
               }
              
               //false意味着数组中不存在这个随机值,那就直接赋值
               arr[i] = r;
           }
           //查看
           printArray(arr);
        }
       
        public static void printArray(int[] arr){
           for(int i = 0;i<arr.length;i++){
               System.out.print(arr[i]);
               if(i != arr.length - 1){
                  System.out.print(",");
               }
           }
           System.out.println();
        }
       
        //优化后的方法:第二个参数表示比较的范围:只比较当前数组中已经赋值的元素!!!
        //优点:1.减少了比较的次数.2.避免了初始值是0值的问题!!!
        public static boolean exists2(int[] arr,int count,int value){
           //遍历数组,比较count之前的值是否和value相等
           for(int i = 0;i<count;i++){
               if(arr[i] == value){
                  return true;
               }
           }
           //程序走到这里,说明for循环中没有碰到相同的数(即:value在数组中不存在)
           return false;
        }
       
        //boolean
        //int[] arr,int value
        public static boolean exists(int[] arr,int value){
           //遍历数组,如果遇到相同的值,就返回true,否则返回false
           for(int i = 0;i<arr.length;i++){
               if(arr[i] == value){
                  return true;
               }
           }
           //程序走到这里,说明for循环中没有碰到相同的数(即:value在数组中不存在)
           return false;
        }
    }
     

     -----------------------------------------------------------------------new-----------------------------------------------------------------

    对象

    一、参数传递的原则:值传递

      Java中,方法调用时,不论形参是基本数据类型还是引用数据类型,

      实际上都是实参的副本传递给方法的形参!!

      数组类型的参数,在方法体外能看到方法体中对数组元素的更改!!

      基本数据类型,在方法体外,看不到方法体中对数据的更改!!

    二、面向对象的概念:

      1.面向对象编程:  

      OOP:object oriented programming,也就是在程序中,直接操作的是对象,而不是一个个的函数!

      

      和此相对应的思想是:面向过程编程思想:procedual(过程化)

      要实现一个功能,每一步的操作都必须自己实现.都是通过一个个的函数调用实现!

      (C语言就是典型的过程化语言!)

      面向对象编程,考虑的是谁有我想要实现的功能:

      举例:

        组装电脑:

        喝咖啡:

        建造汽车:

      2.面向对象思想的好处:

        1> 让程序员从执行者变成了指挥者

        2> 更符合人类思维的编程思想!

        3> 将复杂的事情简单化!

      面向对象开发,实际上就是维护对象之间的关系:

      例如:张三会开锁,李四会撬门,王五会开叉车.

    if(张三.开锁() == ok){
        王五.开叉车();
    }else if(李四.撬门() == ok){
        王五.开叉车();
    }else{
        撤退!!!
    }
    

      3.面向对象的三大特点:

        封装,继承,多态  -- 后面详讲!!!

    三、类和对象:

      1.类:是对现实世界中事物的一种抽象表示!

      2.现实世界中事物的描述方法:

        1>静态的属性信息:颜色,价格,尺寸大小...

        2>功能或者行为:run,eat...

      3.Java中使用类来描述事物:

          电脑:          Java类:

          属性信息    ->  成员变量:

          功能或者行为->  成员方法:

    例如:

    public class Computer{
        //成员变量
        String color = "black";
        double price = 2000.0;
        int size = 16;
        //成员方法
        public void playMusic(){...}
        public void playMovie(){...}
    }

    4.类是一类事物的抽象形式:

      如何来的?

      应该是现实真实存在的一类事物,或者是脑海中的一个概念!

      将它们共同的属性和行为抽取出来就是类!!

      类一般情况下,都不能直接使用.

    必须创建对象!!

    从类到具体的对象.称为实例化过程(创建).

    Person类定义的过程:

     

    Dog类定义的过程:

    四、类成员的写法:

      1.成员变量:

          和之前定义变量的规则一样

          写在类中,成员方法的外边

      2.成员方法:

          和之前定义方法的规则一样

          暂时去掉static

    NoteBook.java

    /*
        NoteBook类的定义:
        一个类一般是不能直接使用的,我们使用的是类所创建的对象.
        使用new关键字,就可以创建一个类的对象(实例化的过程).
       
        一般情况下是在main方法中创建对象.
        main方法可以写在普通类中,或者是一个单独的测试类中.
       
        创建对象的语法:
           类名 对象名 = new 类名();
       
        对象的使用:
           访问对象的成员变量
           调用对象的成员方法
       
        main方法和普通类没有所属关系,一般都会单独的放到一个专门的测试类中.
        这个测试类主要目的就是为了放main方法.!!!
       
    */
    public class NoteBook{
        //成员变量
        String brand = "ASUS";
        int memory = 8;
        int price = 6000;
        String owner = "张三";
       
        //成员方法
        public void type(String content){
           System.out.println("正在打印: " + content);
        }
        //
        public void playMusic(String name){
           System.out.println("播放歌曲: " + name);
        }
       
        //显示自己的属性信息
        public void showInfo(){
           System.out.println("brand : " + brand + ", memory : " + memory + ", price : " + price + ", owner : " + owner);
        }
       
        /*
        //在普通类中写main方法
        public static void main(String[] args){
           //在这里创建对象
           NoteBook book1 = new NoteBook();
          
           //访问book1 的成员变量
           System.out.println("book1.brand : "+ book1.brand);
           System.out.println("book1.price: " + book1.price);
           System.out.println("book1.memory: " + book1.memory);
           System.out.println("book1.owner : " + book1.owner);
          
           //调用book1的成员方法
           book1.type("hello world");
           book1.playMusic("<<我站在草原望北京>>");
           book1.showInfo();
          
        }
        */
    }

    五、对象的创建

    格式:

    类名 对象名 = new 类名();

    NoteBookDemo.java

    /*
        NoteBook类的测试类:
        如果在源文件中出现了没有经过编译的源文件,那就一起编译!!!
       
    */
    public class NoteBookDemo{
        public static void main (String[] args){
           //创建对象
           NoteBook book1 = new NoteBook();
          
           //访问book1 的成员变量
           System.out.println("book1.brand : "+ book1.brand);
           System.out.println("book1.price: " + book1.price);
           System.out.println("book1.memory: " + book1.memory);
           System.out.println("book1.owner : " + book1.owner);
          
           //调用book1的成员方法
           book1.type("hello world");
           book1.playMusic("<<我站在草原望北京>>");
           book1.showInfo();
          
        }
    }

    对象的使用:

      目前,对象基本上就是两个方面可供使用:

        > 成员变量的访问(access)

        > 成员方法的调用(invoke/call)

      

    •   成员之间是可以互相使用的!
    •   成员变量可以使用成员方法的返回值
    •   成员方法可以使用成员变量的值!

    六、一个对象的内存图解:

    重点:

    方法区的概念

    成员变量的初始化

    方法区:用于存放.class字节码文件和方法定义的空间(方法并不是每个实例对象都保存一份,只是引用了方法定义的地址而已!!方法区又称为共享区!!!)

    成员变量的初始化:系统的默认初始化之后,才进行显式的初始化!

    七、两个对象的内存图解:

    .class字节码文件只是第一次使用时加载,以后再次使用,不会多次加载!!!

    不同对象有自己不同的成员变量值,但是方法都是引用方法区中的地址!!!

    八、两个变量指向同一个对象图解:

    重点:

    多个对象名对实例对象成员变量的更改,通过其它对象名也是可以看到的.

    重点:

    1.方法区中存放的是程序中使用到的.class字节码文件,同一个字节码文件会在第一次使用时加载,不会多次加载.

    2.不同对象中并不会保存方法的代码,只是保存了方法的地址引用而已.也就是说:方法区中的东西都是被不同的对象所共享的.方法区也称为共享区!

    3.在对象的创建时,对象的成员变量首先进行默认的初始化,然后是显式的初始化(在类定义时对成员变量的赋值!).

    在对象创建后,可以通过对象名.成员变量名的方式对成员变量进行更改!

    Dog d = new Dog();

    d.name = "abc";//如果没有显式初始化的话,name这个变量被赋值了两次:

    第一次是jvm默认初始化,第二此时用对象名.变量名的方式赋值!

    =============

    main方法一般是单独放到一个源文件中,

    为了查找类方便.合二为一啦!

    把普通类定义和含main方法的测试类放到一个源文件中!!

    /*
        对Phone类的测试类
        
    */
    
    /*
        自定义手机类
        
    */
    class Phone{
        //成员变量
        String brand; //null
        int price = 2000;
        
        //成员方法
        public void call(String name){
            System.out.println("给 " + name + " 打电话");
        }
        //
    }
    
    public class PhoneDemo{
    
        public static void main(String[] args){
            //创建对象
            Phone p = new Phone();
            
            //先对成员变量赋值
            p.brand = "iphone";
            p.price = 8000;
            System.out.println("品牌: " + p.brand + ",价格: " + p.price);
            
            //调用成员方法
            p.call("Obama");
        }
        
    }
    题目:以Phone p = new Phone();这条语句为例,简述在内存中都发生了什么样的变化!
    1. 在Phone对象的创建时,对象的成员变量首先进行默认的初始化,然后是显式的初始化(在类定义时对成员变量的赋值!)
    2. 在堆空间中开辟一片空间,把成员变量赋值(默认的初始化值,显示初始化)
    3. 把对象把对象的内存的空间地址值赋值给变量p
    4. main方法一般单独放到一个原文件当中,为了查找方便,把普通类定义和含main方法的测试类放到一个源文件当中
  • 相关阅读:
    vm12序列号
    三星手机官方固件下载
    MSTP故障处理手册
    分享一个高清壁纸网站
    ThinkPad X220 完美黑苹果 Hackintosh OS X 10.11 El Capitan
    一句命令激活windows/office
    Win10+VMplayer12中U盘无法挂载解决
    记一次金士顿DT100 G3 32G修复
    飘雪代码2枚
    禁用安全模式
  • 原文地址:https://www.cnblogs.com/akinodoo/p/9865275.html
Copyright © 2011-2022 走看看