面向对象不同称呼

image.png
image.png

局部变量

image.png

关于变量的赋值

image.png

三元运算符

image.png

instance of

instanceof运算符用法
运算符是双目运算符,左面的操作元是一个对象实例,右面是一个类.当左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false
image.png

this关键字

image.png
image.png
这时想要区分前面的age是属性,后面的age是形参,就需要使用到this关键字
this可以理解为当前对象/当前正在创建的对象

optional类

image.png
image.png
image.png

虚拟方法

image.png

instance of关键字

image.png

equals()的使用

回顾==的使用image.png
image.png

equals使用

image.png
image.png

重写equals()

先比较当前对象和形参的引用地址是否相同
image.png
image.png
手写比较麻烦,又经常使用可以自动生成hashcode()和equals()。

toString方法的使用

image.png

static

main方法是一个静态方法,不能去直接调用非静态的方法,需要先创建一个对象,对象可以去调用静态方法。

simpledateformat

image.png
image.png

JDK8中日期时间API

image.png
image.png

泛型

在使用泛型的时候不能是基本数据类型,必须要使用他的包装类
image.png
image.png
泛型的构造器不要加,但是在实例化的时候需要加上,image.png
image.png
image.png

内部类

image.png

匿名内部类

以前是要通过四步去调用接口中的方法
image.png
现在使用匿名内部类只需要一步
image.png
这样就是已经写成了一个Inter接口的实现类了。
那么对于实现类来说,就需要去实现里面的抽象方法了。
image.png
image.png
这一个整体就是一个实现了Inter接口的实现类对象。
因为是一个对象,所以就可以去调用方法了。
image.png

  1. public class InclassTest {
  2. public static void main(String[] args) {
  3. myinterImpl myinter = new myinterImpl();
  4. myinter.show();
  5. System.out.println("**************");
  6. new myinter(){
  7. @Override
  8. public void show() {
  9. System.out.println("重写后的匿名方法");
  10. }
  11. }.show();
  12. }
  13. }
  14. interface myinter{
  15. void show();
  16. }
  17. class myinterImpl implements myinter{
  18. @Override
  19. public void show() {
  20. System.out.println("重写方法");
  21. }
  22. }

这样只能调用接口中的一个方法

当当前接口中存在多个方法时

就可以在前面使用一个父类,或者父接口的引用去接收一下。就能以多态的形式把它接收过来。
image.png

枚举类

当一个对象只有有限个,确定的这个类就叫做枚举类
枚举类中的主要方法
image.png

Java比较器

image.png

Arrays工具类

“Arrays.asList的作用是将数组转化为list,一般是用于在初始化的时候,设置几个值进去,简化代码,省去add的部分。”

集合

image.png
虚线是实现关系,实现是继承关系

Collection接口方法

image.png
image.png
image.png

集合的遍历

image.png
image.png
image.png

foreach循环

image.png
过程:coll取出来赋给obj,然后打印出来。底层使用的也是迭代器。

List接口

image.png

ArryayList

ArrayList的源码分析

  • jdk 7情况下
    ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
    list.add(123);//elementData[0] = new Integer(123);

    list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。
    默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。

    结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

    jdk 8中ArrayList的变化:
    ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没创建长度为10的数组
    list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]

    后续的添加和扩容操作与jdk 7 无异。
    2.3 小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存。

List中常用方法

image.png
index of如果不存在返回-1

Set接口

|——Collection接口:单列集合,用来存储一个一个的对象
|——Set接口:存储无序的、不可重复的数据 —>高中讲的“集合”
|——HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
|——LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历
在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据。 对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
* |——TreeSet:可以照添加对象的指定属性,进行排序。

以HashSet为例说明:
1. 无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
2. 不可重复性:保证添加的元素照equals()判断时,不能返回true.即:相同的元素只能添加一个。

保证不可重复性的话能想到的就是一个一个元素去equals比较,这样效率很低,Hashset采用的是hash值

重写equals()和hashcode()

image.png
5. 存储对象所在类的要求:
HashSet/LinkedHashSet:

要求:向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()
要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

TreeSet:
1.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0.不再是equals().
2.定制排序中,比较两个对象是否相同的标准为:compare()返回0.不再是equals().

  1. TreeSet的使用
    6.1 使用说明:
    1.向TreeSet中添加的数据,要求是相同类的对象。
    2.两种排序方式:自然排序(实现Comparable接口 和 定制排序(Comparator)

Map接口

image.png
|——Map:双列数据,存储key-value对的数据 —-类似于高中的函数:y = f(x)
|——HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
|——LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
对于频繁的遍历操作,此类执行效率高于HashMap。
|——TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树
|——Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
|——Properties:常用来处理配置文件。key和value都是String类型


HashMap的底层:数组+链表 (jdk7及之前)
数组+链表+红黑树 (jdk 8)

存放的都是一个一个的entry。

Map结构的理解:

Map中的key:无序的、不可重复的,使用Set存储所的key —-> 如果要放一个自定义的类,key所在的类要重写equals()和hashCode() (以HashMap为例)
>Map中的value:无序的、可重复的,使用Collection存储所的value —->value所在的类要重写equals()
> 一个键值对:key-value构成了一个Entry对象。
>Map中的entry:无序的、不可重复的,使用Set存储所的entry

HashMap在jdk7中实现原理:

HashMap map = new HashMap():
在实例化以后,底层创建了长度是16的一维数组Entry[] table。
…可能已经执行过多次put…
map.put(key1,value1):
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果此位置上的数据为空,此时的key1-value1添加成功。 ——情况1
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。——情况2
如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
如果equals()返回false:此时key1-value1添加成功。——情况3
如果equals()返回true:使用value1替换value2。

补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。

在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原的数据复制过来。

HashMap在jdk8中相较于jdk7在底层实现方面的不同:

  1. new HashMap():底层没创建一个长度为16的数组
    2. jdk 8底层的数组是:Node[],而非Entry[]
    3. 首次调用put()方法时,底层创建长度为16的数组
    4. jdk7底层结构只:数组+链表。jdk8中底层结构:数组+链表+红黑树。
    4.1 形成链表时,七上八下(jdk7:新的元素指向旧的元素。jdk8:旧的元素指向新的元素)
    4.2 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。

“七上八下”说的就是jdk7中,在链表中,新元素放在上面,旧元素放下面,JDK8相反

Map中常用方法

image.png

Map的遍历

image.png

HashTable

image.png
image.png

Collections工具类

image.png
image.png

IO流

Java反射机制

原本是在一个包内创建一个类,再去new一个对象,反射就是通过一个对象去知道他的类,还能知道他在哪个包下。
image.png
image.png
image.png

主要的API

image.png

反射之前

image.png

反射之后

image.png
反射的强大,调用类的私有结构
image.png
image.png
image.png

疑问1:

通过直接new的方式或反射的方式都可以调用公共的结构,开发中用哪个?
答:建议:直接new的方式

疑问2:

什么时候会用反射的方式?
答:反射的特征:动态性。 在运行期间不知道该造哪个对象的时候,需要用到反射

疑问3:

反射机制与面向对象的封装性是不是矛盾的?如何看待两个技术?
答:不矛盾,封装性是建议怎么调用的事情,反射是能不能调用的问题。

关于java.lang.Class类的理解

image.png

获取Class实例的四种方式

方式一:调用运行时类的属性

image.png

方式二:通过运行时类的对象

image.png

方式三:调用Class的静态方法:forName(String classPath)

image.png

方式四:使用类的加载器:classloader(了解)

image.png
总体使用频率上来说,方式三使用的比较多。
image.png
image.png
image.png
image.png
image.png
image.png
image.png

创建运行时类的对象

image.png
image.png

获取运行时类的完整结构(了解)

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

调用运行时类的指定结构

调用运行时类指定属性

image.png
由于这种方式获取的属性权限必须是public的,所以一般不使用此方式。

调用指定的属性:
@Test
public void testField1() throws Exception {
    Class clazz = Person.class;

    //创建运行时类的对象
    Person p = (Person) clazz.newInstance();

    //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
    Field name = clazz.getDeclaredField("name");

    //2.保证当前属性是可访问的
    name.setAccessible(true);
    //3.获取、设置指定对象的此属性值
    name.set(p,"Tom");

    System.out.println(name.get(p));
}

调用运行时类指定方法

调用指定的方法:
 @Test
    public void testMethod() throws Exception {

        Class clazz = Person.class;

        //创建运行时类的对象
        Person p = (Person) clazz.newInstance();

        /*
        1.获取指定的某个方法
        getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表
         */
        Method show = clazz.getDeclaredMethod("show", String.class);
        //2.保证当前方法是可访问的
        show.setAccessible(true);

        /*
        3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
        invoke()的返回值即为对应类中调用的方法的返回值。
         */
        Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
        System.out.println(returnValue);

        System.out.println("*************如何调用静态方法*****************");

        // private static void showDesc()

        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        //如果调用的运行时类中的方法没返回值,则此invoke()返回null
//        Object returnVal = showDesc.invoke(null);
        Object returnVal = showDesc.invoke(Person.class);
        System.out.println(returnVal);//null

    }

调用运行时类中的指定构造器

调用指定的构造器:
@Test
public void testConstructor() throws Exception {
    Class clazz = Person.class;

    //private Person(String name)
    /*
    1.获取指定的构造器
    getDeclaredConstructor():参数:指明构造器的参数列表
     */

    Constructor constructor = clazz.getDeclaredConstructor(String.class);

    //2.保证此构造器是可访问的
    constructor.setAccessible(true);

    //3.调用此构造器创建运行时类的对象
    Person per = (Person) constructor.newInstance("Tom");
    System.out.println(per);

}

JDK8新特性

lambda表达式

image.png

Lambda表达式的使用

image.png
image.png
->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只一个参数,其一对()也可以省略
->右边:lambda体应该使用一对{}包裹;如果lambda体只一条执行语句(可能是return语句,省略这一对{}和return关键字
image.png

语法格式一:无参,无返回值

image.png

语法格式二:Lambda需要一个参数,但是没有返回值

image.png

语法格式三:数据类型可以省略,因为是由编译器推断得出,成为”类型推断”

image.png
image.png

语法格式四:Lambda若只需要一个参数时,参数的小括号可以省略

image.png

语法格式五:Lambda需要两个两个或者以上的参数,多条执行语句,并且可以有返回值

image.png

语法格式六:当Lambda体只有一个语句时,return与大括号若有,都可以省略

image.png

函数式接口

如果一个接口中,只声明了一个抽象方法,则此接口就成为函数式接口
image.png
image.png
image.png
image.png

Optional

image.png

创建optional对象

image.png