JAVA语言程序设计第五章

第五章:Java高级特征

5.1两个关键字

5.1.1static

  • 成员变量声明时使用static,则该变量成为类变量或静态变量不允许修饰局部变量

  • 加载该类时,只分配一次空间,并初始化,在该类所有实例之间是共享的

  • 静态变量&实例变量

    • 静态变量前要加static关键字,而实例变量前则不加
    • 类的静态变量在内存中只有一个,java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享。静态变量可以直接通过类名进行访问,其生命周期取决于类的生命周期
    • 实例变量取决于类的实例。每创建一个实例,java虚拟机就会为实例变量分配一次内存,实例变量位于堆区中,其生命周期取决于实例的生命周期
  • 在类的成员方法声明中带有static关键字,则该方法就成为类方法和静态方法。可以直接被类调用,而不需要生成任何实例

public class GeneralFunction{
	public static int addUp(int x, int y){
		return x+y ;
		}
}
public calss UseGeneral{
	public void method(){
		int c = GeneralFunction.addUp(9,10);
	}
}
  • 静态变量和静态方法
    1. 静态方法和静态变量是属于某一个类,而不属于类的对象
    2. 静态方法和静态变量的引用直接通过类名调用
    3. 可以用类的对象来调用静态的方法和访问静态变量
    4. 在静态方法中不能调用非静态的方法和引用非静态的成员变量, 反之,则可以
    5. 静态方法中不能使用this、super关键字
  • 子类不能重写父类的静态方法,但在子类中可以声明与父类静态方法相同的方法(子类的静态方法被隐藏)
class Parent {
    public static void add() {
     System.out.println("Parent");}
}
class Children extends Parent {
    public  static void add() {
     System.out.println("Children");}
}
public class TestStaticMethod {
public static void main(String[] args) {
     Children ch = new Children(); //Children
    // Parent ch = new Children(); //Parent  向上转型
    //Children c = (children) ch;
    //c.add();  //Children
     ch.add();
 	}
}
  • 没有存在于任何方法体中的静态语句块。在加载该类时执行且只执行一次
public Class StaticInitDemo{
   static int i=5;
    static {
       System.out.println("Static code: i="+ i++);
        }
}
public class Test {
	public static void main(String args[]){
	System.out.println(" Main code: i="+StaticInitDemo.i);
	    }
}
//运行结果
Static code: i=5
Main code: i = 6

5.1.2final

  • 被定义成final的不能有子类,即不能被继承
  • 被定义成final的成员方法不能被重写,但可以被继承
    1. 把方法锁定,防止任何继承类修改它的意义和实现
    2. 高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率
  • 被定义成final的成员变量不能改变。该变量实际上是常量,一般大写,并赋值
    final int NUMBER = 100;
    为了节省内存空间,我们常将常量声明为 static,final。如:
    static final double PI=3.1415926;
  • final变量的赋值:
    • 普通成员变量可默认初始化,但是final类型的成员变量必须显式地初始化
    • 对于final类型的实例变量,可以在定义变量时初始化,或者在构造方法中初始化
    • 对于final类型的静态变量,可以在定义变量时初始化,或者在静态代码块中初始化
public class FinalVarTest {
	final int finalVar1=1; //声明final变量并显式初始化
	final int finalVar2;    //声明final变量
	static final int finalVar3;//声明final类型的静态变量
	public FinalVarTest(){
		finalVar2=2;        //构造方法中进行初始化
	}
	static {
		finalVar3=1;      //在静态代码块中进行初始化
	}
}
  • final方法会在编译的过程中利用内嵌机制进行inline优化;
    inline优化是指:在编译的时候直接调用函数代码替换,而不是在运行时调用函数

5.2抽象类与接口

5.2.1抽象类

  • 一个类如果只声明方法而没有方法的实现,则称为抽象类
    • 必须在声明中增加 abstract 关键字,在无方法体的方法前也要加上abstract
    • 抽象类也可有普通的成员变量或方法
  • 抽象类不能直接用来生成实例,一般可通过定义子类进行实例化
  • 可以生成抽象类的变量,该变量可以指向具体的一个子类的实例
abstract class Employee{
	abstract void raiseSalary(int i);   
}
class Manager extends Employee{
	void raiseSalary(int i ){.}
}
Employee e = new Manager( );
  • 抽象类的特点:
    • 抽象类不一定要包含抽象方法,若类中包含了抽象方法,则该类必须被定义为抽象类
    • 如果一个非抽象类是某个抽象类的子类,它必须重写父类所有的抽象方法,子类对抽象方法的重写不能降低访问权限
    • 抽象类不能被实例化 (不能用new创建对象), 必须被继承,抽象方法必须在子类中被重写,抽象类不用final修饰
    • 抽象方法只需声明,无需实现;不能加final、private、static修饰符
    • 构造方法、静态方法不能被声明为抽象方法
    • 抽象类声明的对象可以成为其子类对象的上转型对象,并调用子类重写的方法

5.2.2接口

  • interface 是在抽象类概念的基础上演变而来的
  • 一个interface所有成员方法都是抽象的,默认具有public,abstract属性。在接口中定义的常量默认为具有public,static,final 属性,且必须给其初值,所以实现类中不能重新定义,也不能改变其值
  • interface定义了一组行为的协议。两个对象之间通过这个协议进行通信
  • interface 不属于类层次结构,不相关的类可以实现相同的接口
  • 实现接口:用implements声明子类,该子类中必须实现接口(及其超类)中的所有方法
  • 接口与多重继承:一个类可只继承一个父类,并实现多个接口,达到多重继承的目的
  • 接口与多态:一个interface 可作为类名使用,实现多态
  • 不能向interface定义中随意增加方法,需要通过继承扩展接口
  • 类分组 package 语句:包(package)是相关类与接口的一个集合,它提供访问控制与命名空间管理
    Java平台中的类与接口都是根据功能以包组织的
    • 每个包都创建一个新的命名空间,因此不同包中的类名不会冲突
接口抽象类
语法interface 接口名{ 方法();}abstract class 抽象类名{ }
实例化不能直接实例化不能直接实例化
方法接口中的方法全部是抽象方法抽象类中的方法不一定全部是抽象方法
继承一个类可以实现多个接口一个子类只能有一个直接父类
成员权限接口中的成员都是public,一般缺省抽象类中的成员不一定是public

5.3泛型与集合类

5.3.1泛型

  • 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
  • 泛型的定义:使用“class 名称<泛型列表>”声明 一个类,为了和普通的类有所区别,这样声明的类称作泛型
public class MyBox<T>{
       private T t;
       public void add(T t){
           this.t = t;
       }
       public T get(){
           reture t;
       }
}
  • 泛型优点:
    • 线程安全
    • 消除强制类型转换

5.3.2集合类

  • 一个集合类对象表示了一组对象,相当于一个容器
1.Set集合
  • Set不能包含重复的元素
  • Set判断两个对象相同不是使用==运算符,而是根据equals()方法
  • 数组与集合区别:
    1. 数组是大小固定的,一旦创建无法扩容;集合大小不固定
    2. 数组的存放的类型只能是一种,集合存放的类型可以不是一种(不加泛型时添加的类型是Object)
    3. 数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查,都是最快的。
      集合操作有丰富的API
  • set相关方法:
//基本操作
int size(); 
boolean isEmpty(); 
boolean contains(Object element); 
boolean add(Object element); 
boolean remove(Object element);
Iterator iterator(); 
//集合元素批操作
boolean addAll(Collection);//并集
boolean containsAll(Collection);
boolean removeAll(Collection);//差
boolean retainAll(Collection);//交集
//数组操作
Object[] toArray():返回一个包含容器中所有元素的数组
Object[] toArray(Object[] a):返回一个包含容器中所有元素的数组,且这个数组不是普通的Object数组,它的类型应该同参数数组a的类型相同(要做类型转换)
  • Set实现类:

    1. HashSet:

      • HashSet集合是采用Hash表存储元素,所以当集合中的元素数量较大时,其访问效率要比线性列表快

      • HashSet集合中的对象是无序的,是根据对象的哈希码确定对象的存储位置

      • 要存放到HashSet的各个对象重写hashCode()和equals()

      • Java规定:如果两个对象值相同,hashCode值一定要相同;如果两个对象的hashCode值相同,它们并不一定相同

      • //定义一个学生类,重写hashCode()和equals()
        class Student{
               int no;
               String name;
               public Student(int no,String name){
                   this.no =no;
                   this.name =name;
               }
            public int hashCode(){  //重写hashCode()方法
                return no ;     //学号即为哈希码
            }
            public boolean equals(Object o){//重写equals()方法
               Student  s = (Student) o;
               return no == s.no && name.equals(s.name);
           }
        }
        
        Set<Integer> s = new HashSet<Integer>();//创建一个HashSet对象,缺省的初始容量是16,加载因子0.75
        
    2. TreeSet:

      • 采用一种有序树的结构(二叉树中序遍历)存储集合中的元素,TreeSet对象中元素按升序排序

      • 实现方法:

        1. 类本身实现Comparable接口,实现compareTo()方法,小于返回负数,等于返回0,大于返回正数

          class Student implements Comparable<Student> {
              private String no;// 学号
              private String name;// 姓名
              private int age;// 年龄
              
          	public Student() {}
          
              public Student(String no, String name, int age) {
                  this.no = no;
                  this.name = name;
                  this.age = age;
          }
          
              @Override
              public String toString() {
              return "学号:" + this.no + ";姓名:" + this.name + ";年龄:" + this.age;
          }
          
              @Override
              public int compareTo(Student o) {
              	return this.no.compareTo(o.no);// 学号升序
                  //int num = (this.age - o.age);//年龄升序
                  //1 return num; //为零,则两个对象值相等,只放一个,升序
                  //2 return num == 0 ? this.no.compareTo(o.no) : num;//年龄升序
          }
          
        2. 定义另一类实现Comparator接口,实现compare()方法

          class Student{
              String no;// 学号
              String name;// 姓名
              int age;// 年龄
          
              public Student() {}
          
              public Student(String no, String name, int age) {
                  this.no = no;
                  this.name = name;
                  this.age = age;
              }
          
              @Override
              public String toString() {
              return "学号:" + this.no + ";姓名:" + this.name + ";年龄:" + this.age;
          	}
          }
          
          class StudentComparator implements Comparator<Student>{
          	@Override
          	public int compare(Student o1, Student o2) {
                  // TODO Auto-generated method stub
                  return o1.age-o2.age;//年龄升序,若两个对象值相等,只放一个
          	}
          }
          
          接口ComparableComparator
          排序逻辑在待排序的类(对象)中实现另定义一个类实现
          排序方法int compareTo(Object o1)int compare(Object o1,Objecto2)
          所在包java.lang.ComparableJava.util.Comparator
          比较方式内部比较器外部比较器
          耦合性强耦合松耦合
    3. LinkedHashSet:

      • LinkedHashSet则是继承了HashSet的子类,使用的是链表结构。也是根据hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,但是由于要维护元素的插入顺序,故性能略低于HashSet的性能
    • 总结:如何选择HashSet和TreeSet,HashSet的性能比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的算法来维护集合元素的大小顺序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet。而HashSet的子类LinkedHashSet,对普通的插入、删除操作,LinkedHashSet比HashSet要稍微慢一点(维护链表开销),但是遍历会更快
2.List集合
  • List是有序的集合,元素可以重复
  • List接口定义:
public interface List extends Collection {    
	// 按位置存取元素    
	Object get(int index);    
	Object set(int index, Object element);         	  // Optional    
	void add(int index, Object element);              // Optional    
	Object remove(int index);                         // Optional    
	abstract boolean addAll(int index, Collection c); // Optional     }
  • List实现:

    1. ArrayList:

      • ArrayList类采用可变大小的数组实现了List接口,ArrayList对象会随着元素的增加其容积自动扩大,是非同步的,是效率最高的也是最常用的

      • 使用连续存储区域保存元素,它是一种直接访问结构,插入和删除操作会影响其他元素的位置

      • //创建
        List list=new ArrayList<String>();//向上转型,提高程序的可扩展性
        //一般方法
        add(e);//增加元素e
        add(pos,e);//在位置pos增加元素e
        set(pos,e);//修改位置pos元素为e
        get(i);//取到位置pos元素
        remove(e);//删除元素e
        remove(pos);//删除位置pos的元素
        
        //遍历方法
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
              System.out.println(iterator.next());
        }
        
        for(String s:list){
            System.out.println(s);
        }
        
        for(int x=0;x<list.size();x++){
            System.out.println(list.get(x));
        }
        
    2. LinkedList:

      • LinkedList类采用链表结构实现List接口,可以用来实现堆栈、队列或双端队列,是非同步

      • 采用双向循环链表结构实现List接口

      • 每个元素除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素,顺序访问结构

      • 插入和删除操作只需修改引用信息,执行效率高

      • //创建
        LinkedList<String> strings = new LinkedList<>();
        //特有方法
        addFirst(Object obj);//在集合第一位添加一个元素
        addLast(Object obj)//在集合最后一位添加一个元素
        getFirst();//得到集合第一位的元素
        getLast();//得到集合的最后一位元素
        removeFirst();//删除集合的第一个元素
        removeLast();//删除集合的最后一个元素
        
    3. Vector:

      • Vector类采用可变大小的数组实现了List接口,是同步
    • 总结:
      • 如果需要遍历List集合元素,ArrayList、Vector集合,则应该使用随机访问方法(get)来遍历集合元素,这样性能更好。对应LinkedList集合,则应采用迭代器(Iterator)来遍历集合元素
      • 如果需要经常执行插入、删除操作来改变List集合大小,则应该使用LinkedList集合
      • 如果多条线程需要同时访问List集合中的元素,可以考虑使用Vector这个同步实现
3.Map集合
  • Map把键值映射到某个值,一个键值最多只能映射一个值
  • Map接口定义:
public interface Map { 
    Object   put(Object key, Object value); 
    Object   get(Object key); 
    Object   remove(Object key); 
    boolean  containsKey(Object key); 
    boolean  containsValue(Object value); 
    int size(); 
    boolean isEmpty();
}  
  • Map实现:

    1. HashMap:

      • 采用Hash表实现Map,是无序的,HashMap是非同步的并允许有空的键与值(null)

      • //创建
        Map<String, Integer> hashMap = new HashMap<>();
        //常用方法
        put();往集合中添加元素,key 值不可重复,重复时会覆盖之前的 value 值
        size();返回集合长度
        get(key);获取对应 key 值的 value 值
        clear();清除集合中的所有元素
        values();返回一个新集合,获取集合中所有元素的 values
        keySet();返回一个新集合,获取集合中所有元素的 key
        remove();根据 key 或者 key-value 去除集合中元素,并分别返回 value 值和 Booleaniterator();返回一个迭代器对象
        entrySet();Map 集合每个 key-value 转换为一个 Entry 对象,并返回由所有的 Entry 对象组成的 Set 集合
        containsKey();判断集合中是否含右指定的 key 值
            
        //遍历方法
        //通过 keySet 遍历,普遍使用
        for (String key : map.keySet()) {
             System.out.println("key= "+ key + " and value= " + map.get(key));
        }
        //通过 entrySet 和迭代器遍历
        Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
        while (it.hasNext()) {
               Map.Entry<String, Integer> entry = it.next();
               System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());   
        }
        
    2. HashTable

      • 采用Hash表实现Map,是无序的
    3. TreeMap

      • 有序树的结构实现了Map的子接口SortedMap,该类将键的升序的次序排列元素

5.4枚举和包装类

  • 集合操作类Collections:
public static void sort(List list); // 自然排序,list 必须实现 Comparable 接口 
public static void reverse(List list);// 按照自然排序,进行反转,即降序 
public static void shuffle(List list); //混排,与 sort 相反,完全打乱排列顺序 
public static void copy(List dest, list src);// 复制,如果 dest 更长,则其剩余元素不受影响
  • 集合的遍历
    • 集合迭代器:是一个访问集合中元素的对象,起始位置处于第一个元素之前
    • 两种迭代器接口:
      1. Iterator:完成迭代器基本功能所需的方法
      2. ListIterator:完成迭代器附加功能所需的方法(双向遍历,修改元素)
  • Map集合的遍历
Set set =map.keySet();
Iterator it=set.iterator();
while(it.hasNext()){
    String s= (String) it.next();
    System.out.println(map.get(s));
}
  • 枚举类型

    • 一般用于表示一组常量,一个枚举声明实际上定义了一个类

    • [public] enum 枚举类型名 [implements 接口名表] {
      				枚举常量定义
      				[枚举体定义]
      }
      
      public enum Names {
        		       Li, Zhang, Wang, Zhao,Chen
      }
      
      Names name = Names.Wang;
      
  • 包装类

    • Wrapper将基本类型表示成类

    • 每个wrapper类对象都封装了基本类型的一个值

    • Primitive Data TypeWrapper Class
      booleanBoolean
      byteByte
      charCharacter
      shortShort
      intInteger
      longLong
      floatFloat
      doubleDouble
    • 装箱:把基本类型的数据通过相应Wrapper类形成对象

    • 拆箱:把一个Wrapper类对象中的基本数据类型提取出来

  • String类型:

    • String不是基本的数据类型,是类类型(引用类型)

    • String是不可变对象,常用的相关类StringBuilder (线程不安全,执行速度快), StringBuffer(线程安全,执行速度慢)

    • String和Integer相互转换:

      • //  String  To  int 
            int i = Integer.parseInt(100);
            int i = Integer.valueOf (100);
        
        //  int   To  String
            String s = String.valueOf(100); 
            String s = Integer.toString(100);
        
    • public static void main(String[] args) {
      		String s1="ab";
      		String s2="a"+"b";
      		String s3=new String("ab");
      		String s4="ab"+"c";
      		String s5=s1+"c";
      		System.out.println(s1==s2);//true
      		System.out.println(s1==s3);//false
      		System.out.println(s4==s5);//false
          	//“==”判断两个对象是否指向同一个引用,即是否为同一个对象
          	//equals方法比较两个字符串的内容是否相等
      }
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值