JavaSE学习笔记基础加强(1)

(1) 静态导入

导入技术其实在java中是为了方便的使用其他人写好的类。

import java.lang.*|类名

在原来的导包语句中发现只能导入类。如果需要导入的是一些静态的方法或者属性那么就无能为力。

举例1:求一个任意半径的圆形的面积?

// 求一个任意半径的圆形的面积

    public static void getArea(){

       // 1. 求一个随机的半径

       double r  = Math.ceil(Math.random()*10);

       // 2. 计算面积

       double area = 0.0;

       area = Math.PI*r*r;

       // 3. 打印面积

       System.out.println("半径是"+r+"的圆形的面积是:"+area);

}

发现以上的代码中大量的出现了一些静态的成员。

那么可以使用静态导入的方式简化代码的书写。

语法:

import static java.lang.*|静态成员

 

实战:

importstatic java.lang.Math.PI;

importstatic java.lang.System.out;

importstatic java.lang.Math.random;

importstatic java.lang.Math.ceil;

public class Demo4 {

    // 求一个任意半径的圆形的面积

    public static void getArea(){

       // 1. 求一个随机的半径

       double r  = ceil(random()*10);

       // 2. 计算面积

       double area = 0.0;

       area = PI*r*r;

       // 3. 打印面积

       out.println("半径是"+r+"的圆形的面积是:"+area);

    }

}

如果代码中使用到了一个类的多个静态成员那么可以直接使用* 进行全部的导入。

import static java.lang.Math.*;

(2)  可变参数

思考:如果开发者现在要定义一个函数(方法),那么不知道参数的个数的时候应该如何指定形参。

语法:定义函数的语法

修饰符 返回值类型 方法名(参数类型… 变量名 ) 异常的声明{

    // 函数体

    return;

}

注:学习可变参数的本质

  1. 可变参数其实是一个可变的数组
  2. 可变参数在方法的声明中只能出现在参数列表的最后一个位置
  3. 可变参数只能在参数列表中出现一次

举例1:求任意个整数的累加和?

// 求任意个整数的累加和?

public static long getSum(int... is){

       long sum = 0;

       for (int i = 0; i < is.length; i++) {

         sum +=is[i];

       }

       return sum;

}

举例2:SUN的API中用的可变参数。

static <T> List<T> asList(T... a) 返回一个受指定数组支持的固定大小的列表。

u  包装类

其实在java中有四型八种的基本数据类型。如果所有的基本数据类型不是对象的话那么java

语言就不是正真的OOP语言。

Wrapper Class即包装类。在包装类中SUN封转了开发者常用的一些属性和方法,可以进行快速的编程。

包装类

基本数据类型

Byte

byte

Short

short

Integer

int

Long

long

Boolean

boolean

Character

char

Float

float

Double

double

举例1:体验Integer类提供的属性。

// 体验Integr类的属性

    public static void getField() {

       System.out.println(Integer.MIN_VALUE);   // -2147483648

       System.out.println(Integer.MAX_VALUE);   // 2147483647

    }

阅读以下的代码,分析代码的错误原因:

long date = 12345678910;   // 报错

12345678910 

2147483647

举例2:体验Integer类提供的方法。

主要学习的是整数到字符串之间的转换的方法。

// 体验Integr类的方法

    public static void getMethod() {

       // 创建类对象

       Integer in1 = new Integer(123);

       int i1 = in1.intValue();

       System.out.println(i1+1);

       // 转换为字符串

       String str1 = in1.toString();

       System.out.println(str1+1);

    }

其实在这里没有必要转型为String的时候进行基本的toString()调用。

简化以上的代码:

// 体验Integr类的方法

    public static void getMethod2() {

       // 创建类对象

       Integer in1 = new Integer(123);

       int i1 = in1;      // 自动拆箱

       System.out.println(i1+1);

       // 转换为字符串

       System.out.println(in1+""+1);

    }

(3)什么是自动拆箱和自动装箱?

自动装箱: 如果将基本类型传递给包装类型。  Integer in1 = 12;

自动拆箱: 如果将包装类型传递给基本类型。  int i1 = in1

在泛型的时候比较有用:

集合:主要的用途是进行对象的存储。

list.add(1);    //自动装箱

思考:String str = “hello”;

u  增强for循环

如果要遍历一个指定的数,那么我们一般要使用传统的的for循环。

语法:

for( 条件的初始化语句; 条件表达式; 循环的增量 ){

   // 循环体  break或continue

}

这样写的话每次都会遇到一个下标越界的一个异常。

因此可以使用增强for循环进行快速的遍历(数组、集合以及实现了Iterable接口的类)。

语法:

for(数据类型 变量名:需要遍历的集合){

    // 循环体

}

举例1:遍历一个普通的数组。

// 遍历一个数组

    public static  void printArray(int [] a){

       for(int temp:a){

           System.out.println(temp);

       }

    }

举例2:遍历一个List集合。

// 遍历一个list

    public static void printList(List<String> list){

       for (String string : list) {

           System.out.println(string);

       }

    }

举例3:遍历一个Map集合。

 

// 遍历一个Map集合

    public static void printMap(Map<Integer,String> map){

       // 想将其转换为实现了Iterable接口的Set类

       Set<Map.Entry<Integer, String>> set = map.entrySet();

       // 遍历set集合

       for(Map.Entry<Integer, String> entry:set){

          // 获取entry对象的key和value值

          Integer key = entry.getKey();

          String value = entry.getValue();

          System.out.println(key+"="+value+",");

       }

    }

思考:如果以上的集合没有使用泛型,那么在使用for循环的时候应该使用什么类型接收集合数据?  Object

问题1:使用增强for循环是否可以改变集合中数据?

因为for循环在遍历的时候使用的是将值拷贝一份给临时变量。因此改变临时变量不会改变集合中的数据值。

问题2:使用增强for循环遍历集合的时候操作集合的问题?

    // 遍历一个list

    public static void printList(List<String> list){

       for (String string : list) {

           list.add("eeee");    // 运行错误

           System.out.println(string);

       }

       System.out.println("遍历中: "+list);

    }

异常信息如下:

Exception in thread "main" java.util.ConcurrentModificationException

模拟基础班看过的场景:

    public static void main(String[] args) {

       List<String> list = new ArrayList<String>();

       list.add("aaaa");

       list.add("bbbb");

       list.add("cccc");

       list.add("dddd");

      

       Iterator<String> it = list.iterator();

       while(it.hasNext()){

           list.add("yyyy");

           String str = it.next();

           System.out.println(str);

       }

    }

运行异常:

Exception in thread "main" java.util.ConcurrentModificationException

总结;

在使用增强for循环进行集合的迭代的时候其实默认使用的是迭代器,因此在循环中不能使用集合的引用变量直接操作集合,避免导致多线程并发访问的安全性异常。

u  安全的枚举类

在实际的项目的开发中我们经常需要一类数据,这一类数据的值是特定范围的一组值。如:

性别:[男、女]

交通灯:[红、黄、绿]

星期几:[一~七]

以上的一组值可以定义为枚举数据类型。

语法:

修饰符 enum 枚举类名{

   // 定义枚举的一组值,多个值之间使用逗号进行分隔

}

实现:

public enum Gender {

  MALE,FEMALE;

}

问题:枚举的本质是什么?

  1. 枚举本质是一个类
  2. 默认继承自Enum类
  3. 枚举值本质是枚举类的静态常量值
  4. 枚举值都在静态代码块中进行初始化
  5. 枚举类的默认构造函数式有参数的且只能私有
  6. 枚举是单例模式
  7. 既然枚举是一个普通类,那么我们开发人员就可以在类中定义类的成员(属性、构造函数、函数)。

    举例1:在枚举中定义属性。

    public enum TrafficLight {

       // 定义枚举值           

       RED,GREEN,YELLOW

       // 定义成员属性

       public String info = "交通灯信息";

       public static void main(String[] args) {

           System.out.println(TrafficLight.GREEN.info);

       }

    }

    举例2::在枚举中定义构造函数。

    public enum TrafficLight {

       // 定义枚举值

       RED("红灯"),GREEN("绿灯"),YELLOW("黄灯");

       // 定义成员属性

       public String info = "交通灯信息";

       // 提供构造函数进行属性的初始化

       private TrafficLight(String info){

           this.info = info;

       }

       public static void main(String[] args) {

           System.out.println(TrafficLight.GREEN.info);

           System.out.println(TrafficLight.RED.info);

           System.out.println(TrafficLight.YELLOW.info);

       }

    }

    切记的是为了保证枚举是单例的那么构造函数全部要私有。

    举例3:在枚举中定义函数。

    public enum TrafficLight {

        // 定义枚举值

        RED("红灯") {

           @Override

           public void showMessage() {

                 System.out.println("红灯停!");

           }

        },

        GREEN("绿灯") {

           @Override

           public void showMessage() {

                System.out.println("绿灯行!");

           }

        },

        YELLOW("黄灯") {

           @Override

           public void showMessage() {

               System.out.println("你自己看着办!");

           }

        };

        // 定义成员属性

        public String info = "交通灯信息";

        // 提供构造函数进行属性的初始化

        private TrafficLight(String info) {

           this.info = info;

        }

        // 提供一个表明灯的信息的方法

        public abstract void showMessage();

        public static void main(String[] args) {

           System.out.println(TrafficLight.GREEN.info);

           System.out.println(TrafficLight.RED.info);

           System.out.println(TrafficLight.YELLOW.info);

           TrafficLight.RED.showMessage();

        }

    }

    以上的代码可见在枚举类中可以定义抽象方法,但是不能将枚举类声明为抽象类,只能在声明枚举值的时候实现所有的抽象方法即(匿名内部类)。

    在实际的枚举中其实自定义的枚举类默认继承Enum类,那么我们的枚举类中就会有Enum类中的定义好的属性和方法。

    常用方法

    方法的描述

    String name()

    获取枚举值的名称

    int ordinal()

    返回枚举值定义的序号

    valueOf(Class<T> enumType, String name)

    通过反射查找指定的类中的指定名的枚举值

    values()

    该方法在API中不可见但是可用

    举例3:使用Enum类中常用的方法。

    // 常用的方法体验

    System.out.println(TrafficLight.YELLOW.name());  // YELLOW

    System.out.println(TrafficLight.RED.ordinal());  // 0

    System.out.println(TrafficLight.valueOf(TrafficLight.class,"GREEN"));

    以上的方法都是在API中可见的方法,但是有一些方法是API中不可见但是内部其实定义了的方法。

    举例4:遍历枚举值。

    // 遍历枚举值

    TrafficLight [] trans = TrafficLight.values();

    for(TrafficLight temp:trans){

    System.out.println(temp);

    }

你可能感兴趣的:(JavaSE)