java基础(一)

一.面向对象

1. == 和 equals 方法

  1.  ==是判断两个变量或实例是不是指向同一个内存空间,equals是判断两个变量或实例所指向的内存空间的值是不是相同 
  2. ==是指对内存地址进行比较 , equals()是对字符串的内容进行比较
  3. ==指引用是否相同, equals()指的是值是否相同
public class basis {
    public static void main(String[] args) {
        int it = 65;
        float f1 = 65.0f;
        System.out.println("65 和 65.0f 是否相等?"+(it == f1));//true
        char ch = 'A';
        System.out.println("65 和 65.0f 是否相等?"+(it == ch));//true

        String str1 = new String("hello");
        String str2 = new String("hello");

        /** str1 和 str2他们都是引用类型变量,分别指向两个通过new关键字创建的String对象,
         * 因此str1 和 str2 两个变量不相等*/
        System.out.println("str1 和 str2 是否相等?"+ (str1 == str2));//false
        System.out.println("str1 是否 equals str2?" + (str1.equals(str2)));//true
    }
}

 

2.final修饰符

    1.final关键字可用于修饰类,变量和方法。

    2.final修饰的变量不可被改变,一旦获得了初始值,该final变量的值就不能被重新赋值。

    3.final修饰的成员变量必须被程序员显式地指定初始值。

 

3.抽象类

    1.抽象方法和抽象类必须使用abstract修饰符来定义,抽象类里可以没有抽象方法,抽象方法不能有方法体。

    2.抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。

    3.抽象类可以包含成员变量,方法,构造器(不能创建实例,主要是被其子类调用),初始化块,内部类(接口,枚举)5种成分。

    4.含有抽象方法的类只能被定义为抽象类。

    5.抽象类只能被当成父类继承。

 

4.接口

    1.接口里不能包含构造器和初始化块定义,可以包含成员变量(只能是静态常量,public static final修饰),方法,内部类(包括内部接口,枚举)定义。

    2.接口里定义的方法只能是抽象方法,类方法,默认方法或私有方法,接口里的普通方法总是使用public abstract 来修饰。

    3.接口里的普通方法不能有方法体,但类方法(static修饰),默认方法(default修饰,不能用static),私有方法都必须有方法体。

 

接口和抽象类

1.共同点

->接口和抽象类都不能被实例化,他们都位于继承树的顶端,用于被其它类实现和继承。

->接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

2.区别

->抽象类可以包含普通方法,接口不能。

->接口只能定义静态常量,抽象类既能定义静态常量,也可以定义普通成员变量。

->接口里不含构造器,抽象类里可以包含构造器。抽象类里的构造器不是用于创建对象,而是让子类调用这些构造器来完成属于抽象类的初始化操作。

->接口不能含初始化块,抽象类可以。

->一个类最多只能有一个直接父类,包括抽象类;但一个类可以直接实现多个接口,通过实现多个接口可以弥补java单继承的不足。

 

二.Java基础类库

1.常用类

Object类

    1.Object类是所有类,数组,枚举类的父类。当一个类没有使用extends关键字为它显式指定父类,则该类默认继承Object父类。

    2.java还提供类一个protected 修饰的 clone()方法,该方法用于帮助其他对象来实现“自我克隆”,所谓“自我克隆”就是得到一个当前对象的副本,而且二者之间完全隔离。由于Object类提供的clone()方法使用protected修饰,因此该方法只能被子类重写或调用。

 

String类

    1.String类是不可变类,一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直到这个对象被销毁。

    2.StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer 被创建以后,通过StringBuffer 提供的append(),insert(),reverse(),setCharAt(),setLength()等方法将其转化为一个String对象。

    3.StringBuilder也代表可变字符串对象。StringBuilder与StringBuffer基本相似,两个类的构造器和构造方法也基本相同。不同的是,StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。因此通常情况下,如果需要创建一个内容可变的字符串对象,则应该优先考虑使用StringBuilder类。

 

 String(StringBuffer buffer):根据StringbBuffer 对象来创建对应的String对象。

String(StringBuilder builder):根据StringBuilder 对象来创建对应的String对象。

 

三.Java集合

1.概述:java集合分为三大类:Set,List,Map

->Set集合类似于一个罐子,无法记住添加元素的顺序,所以Set是无序的,且里面的元素不能重复。只能根元素本身来访问。

->List集合非常像一个数组,可以记住每次添加元素的顺序,所以List是有序的,且List长度可变。可以直接根据元素的索引访问。

->Map集合也像一个罐子,只是它里面的每项数据都由两个值组成。可以根据每项元素的key来访问其value。

 

2.Set集合

->Set集合是不能重复的,用iterator()方法来区分重复与否

HashSet类,LinkedHashSet类,TreeSet类,SortedSet(接口),EnumSet

   1.HashSet类

   ->不能保证元素的排列顺序,顺序可能与添加顺序不同

   ->HashSet不是同步的,如果多线程同时访问修改了HashSet集合时,必须通过代码保证其同步。

   ->集合元素值可以为null。

   ->当向HashSet集合中存入一个元素时,HahSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法比较返回true,但他们的hashCode()方法返回值不相等,HashSet将会把他们存储在不同的位置,依然可以添加成功。也就是说,HashSet集合判断两个元素是否相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

注意:当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,则应该重写其hashCode()方法。规则是:如果两个对象通过equals()方法比较返回true,这两个对象的hashCode值也应该相同。

 

   2.LinkedHashSet 类

   ->LinkedHashSet 集合也是根据元素的hashCode值来决定元素的存储位置

   ->他同时使用链表维护元素的次序,输出时,元素的顺序总是与添加顺序一致。

   ->因为需要用链表维护内部顺序,所以性能略低于HashSet,但也因此在迭代访问Set里的全部元素时将有很好的性能。

 

   3.TreeSet类

   ->TreeSet是SortedSet接口的实现类,正如Sorted名字所暗示的,TreeSet可以确保元素集合处于排序状态。

   ->与HashSet集合不同,TreeSet采用红黑树的数据结构来存储集合元素。

   ->TreeSet支持两种排序方法:自然排序和定制排序。在默认情况下,TreeSet采用自然排序。

   ->如果希望TreeSet能正常运行,TreeSet只能添加同一类型的对象。

   ->对于TreeSet集合而言,他判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)方法比较是否返回0---如果比较返回0,TreeSet会认为他们相等,否则就不相等。

    ->当把一个对象加入TreeSet集合中时,TreeSet调用compareTo(Object obj)方法与容器中的其他对象比较大小,然后根据红黑树结构找到他的存储位置。如果两个对象比较相等,则新对象无法加入进来。

 

3.List集合

ArrayList类,LinkedList类    

   1. ArrayList类

    ->ArrayList 底层是基于数组来实现容量大小动态变化的。即是一个其容量能够动态增长的动态数组。

    ->基本的ArrayList,长于随机访问元素,但是在List中间插入和移除元素时较慢。同时,ArrayList的操作不是线程安全的!一般在单线程中才使用ArrayList,而在多线程中一般使用Vector或者CopyOnWriteArrayList

 

   2.LinkedList类

   ->LinkedList 是一个继承于AbstractSequentialList的双向链表。底层是链表,它也可以被当作堆栈、队列或双端队列进行操作。 
   ->LinkedList 实现 List 接口,能对它进行队列操作。 
   ->LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。 
   ->LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。 
   ->LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。 
   ->LinkedList 是非同步的。

 

    3.ArrayList 与 LinkedList

      ArrayList 内部以数组形式保存集合中的元素,数组以一块连续内存区来保存所有的数组元素,所以所有以数组为底层的集合在随机访问时性能都比较好,而LinkedList内部以链表形式保存集合中的元素,在执行插入,删除操作时有较好的性能。

     总体来说,ArrayList的性能比LinkedList要好,因此大部分时候都应该优先考虑使用ArrayList。

 

4.Map集合

->Map的key不允许重复,key与value之间单向一一对应。

->如果把Map中的所有key放在一起来看,他们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复)。Map的实现类和子接口中的key集的存储形式和对应Set集合中的存储形式完全相同。

->如果把Map中的所有value放在一起来看,他们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引(key)查找。

HashMap类,Hashtable类,LinkendHashMap类,SortedMap(接口),TreeMap类,EnumMap类

 

    1.HashMap和Hashtable实现类

     ->HashMap是线程不安全的实现,所以HashMap比Hashtable的性能高一点,如果有多个线程访问同一个Map对象时,使用Hashtable实现类会更好。

     ->Hashtable不允许使用null作为key和value,HashMap可以使用null作为key或value(可同时为null,但只能有一对),其中可有多个value为null,但只能有一个key为null。

     ->HashMap里的key不能重复,所以HashMap里最多有一个key-value对的key为null,但可以有无数多个key-value对的value为null。

     ->HashMap,Hashtable不能保证其key-value对的顺序。

     ->HashMap和Hashtable判断两个key相等的标准:两个对象通过equals()方法比较返回true,两个key的hashCode值也相等

     ->HashMap和Hashtable判断两个value相等的标准:只要两个对象通过equals()方法比较返回true即可。

 

    2.LinkedHashMap实现类

    ->LinkedHashMap是HashMap的子类

    ->LinkedHashMap 使用双向链表来维护key-value对的次序(其实只需要考虑key的次序),该链表负责维护Map的迭代顺序,迭代顺序与key-value对的插入顺序保持一致。

    ->forEach()方法遍历Map集合:

import java.util.LinkedHashMap;

public class LinkedHashMapTest {
    public static void main(String[] args) {
        LinkedHashMap scores = new LinkedHashMap();
        scores.put("语文",80);
        scores.put("数学",82);
        scores.put("英语",100);
        //调用forEach()方法遍历scores里的所有key-value对
        scores.forEach((key,value) -> System.out.println(key + "-->" + value));
    }
}
语文-->80
数学-->82
英语-->100

   3.SortedMap接口和TreeMap实现类

   ->Map接口派生出一个SortedMap子接口,Sorted'Map接口有一个TeeMap实现类。

   ->TreeMap是一个红黑树结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对时需根据key对节点进行排序(key-value对总是处于有序状态,无需专门进行排序操作)。TreeMap有两种排序方式:

          ->自然排序:key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则会抛出ClassCastException异常。

         ->定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对key进行排序。采用定制排序不要求Map的key实现Comparable接口。

   ->TreeMap中判断两个key相等的标准:两个key通过compare To()方法返回0则相等。

   ->如果使用自定义类作为TreeMap的key,则重写该类的equals方法和compare To()方法时应保持一致的返回结果:两个key通过equals()方法比较返回true时,他们通过compare To()方法比较应该返回0。

 

   4.EnumMap实现类

   ->EnumMap内部以数组形式保存,里面的所有key都必须是单个枚举类的枚举值,创建EnumMap时必须指定一个枚举类。

   ->EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)来维护key-value对的顺序。

   ->EnumMap不允许使用null作为key,但允许使用null作为value。如果使用null作为key则会抛出NullPointerException异常。

 

四.泛型

一个最普通的泛型类:

/**此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
 *在实例化泛型类时,必须指定T的具体类型*/
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;
 
    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }
 
    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

泛型的类型参数只能是类类型(包括自定义类),不能是简单类型:

//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);
Log.d("泛型测试","key is " + genericInteger.getKey());

 
//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");
Log.d("泛型测试","key is " + genericString.getKey());


//结果
12-27 09:20:04.432 13063-13063/? D/泛型测试: key is 123456
12-27 09:20:04.432 13063-13063/? D/泛型测试: key is key_vlaue

在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。

Generic generic = new Generic("111111");
Generic generic1 = new Generic(4444);
Generic generic2 = new Generic(55.55);
Generic generic3 = new Generic(false);
 
Log.d("泛型测试","key is " + generic.getKey());
Log.d("泛型测试","key is " + generic1.getKey());
Log.d("泛型测试","key is " + generic2.getKey());
Log.d("泛型测试","key is " + generic3.getKey());
D/泛型测试: key is 111111
D/泛型测试: key is 4444
D/泛型测试: key is 55.55
D/泛型测试: key is false

 

2.泛型接口

泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子:

//定义一个泛型接口
public interface Generator<T> {
    public T next();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值