栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java基础学习

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java基础学习

Java基础学习
  • Java变量
    变量:变量是程序中最基本的存储单元,由变量类型,变量名和存储的值组成。它是内存中的一个存储的区域,这个区域里的数据在同一数据类型中可以不断的变化。
    变量用于在内存中保留可变的数据。
    变量类型:数值型,字符型,布尔型。
    变量中又存在成员变量和局部变量。
    成员变量:在方法体外,类体内声明的变量称为成员变量。
    成员变量中:
    实例变量:不以static修饰,这些成员变量是对象中的成员,实例变量随着对象的建立而存在于堆内存中。生命周期随着对象的消失而消失。
    类变量:以static修饰,也叫静态变量具有以下特点:随着类的加载而加载,优先于对象存在,被所有对象所共享,可以直接被类名调用。类变量随着类的加载而存在于方法区中。生命周期随着类的消失而消失。
    局部变量:在方法体内部声明的变量称为局部变量。

  • Java命名规则
    所有标识符都应该以字母(A-Z或者a-z)、美元符($)、或者下划线(_)开始,但不能以数字开头,关键字不能用作标识符,标识符是大小写敏感的;
    包的命名规则:包名统一使用小写,点分隔符之间有且仅有一个自然语义的英文单词或者多个单词连接到一块儿。包名统一使用单数形式,如果类名有复数含义,则可以使用复数形式。
    类的命名规则:类的首字母必须大写,多个单词组成的类名使用大驼峰命名法;
    变量及方法的命名规则:变量名和方法名首字母小写,多个但单词组成的变量名和方法名使用小驼峰命名法。

  • Java中的数据类型与包装类
    基本数据类型:四类八种:
    整数类:Byte:使用1个字节存储,范围为-128~127;
    short:使用两个字节存储,范围为-32768~32767;
    int:使用4个字节存储,范围:正负21亿
    long:使用8个字节存储
    浮点类:Float:单精度,使用4字节存储,精度可以精确到小数点后7位有效数字
    double:双精度,使用8字节存储,精度是float的2倍
    字符类
    布尔类
    Java有八种基本数据类型:byte、short、int、long、float、double、boolean、char
    Java为其提供了8种对应的包装类:Byte、Short、Integer、Long、Float、Double、Boolean、Character
    即将每个基本类型都包装成了一个类。常用的包装类可以分为三类:Character、Number、Boolean。
    包装类的作用:集合不允许存放基本数据类型,故常用包装类;
    包含了每种基本数据类型的相关属性,如最大值、最小值、所占位数等;
    作为基本数据类型对应的类类型,提供了一系列实用的对象操作,如类型转换、进制转换等等。
    所有包装类都可以将与之对应的基本数据类型作为参数来创建它们的实例对象;
    除了Character类之外,其他包装类都可以将一个字符串作为参数来构造它们的实例;
    Boolean类的构造方法参数为String类型时,若该字符串为true(不论大小写),则该对象表示true,否则表示false;
    当包装类Number构造方法的参数为String类型时,字符串不能为null,并且该字符串必须能够解析为基本类型的数据
    包装类和基本数据类型的区别:
    包装类是对象,拥有方法和字段,对象的调用都是通过引用对象的地址;基本类型不是;
    包装类型是引用的传递;基本类型是值的传递 ;
    声明方式不同:
    基本数据类型不需要new关键字;
    包装类型需要new存储位置不同:
    基本数据类型直接将值保存在值栈中;
    包装类型是把对象放在堆中,然后通过对象的引用来调用他们 在堆内存中进行new来分配内存空间
    初始值不同:
    int的初始值为 0 、 boolean的初始值为false
    包装类型的初始值为null
    使用方式不同:
    基本数据类型直接赋值使用就好;
    包装类型是在集合如 coolectionMap时使用

  • 封装、继承、多态
    封装:将要使用的属性和方法放在一个类的内部,仅对外提供一个接口可以通过接口调用这些属性和方法。
    继承:所有的类都默认直接或者间接继承Object类。JAVA中类只有单继承,无多继承。私有的东西无法被类继承。
    多态:多态出现于子类对父类的继承,多态是方法的多态不是属性的多态,当子类要使用父类的某一方法时,而不同的子类对该方法有不同的实现方式,从而产生了多态。

  • 对象和类
    类是用于创建对象的模板,通过类可以快速创建一个对象。反过来也可以说对象是类的实例化,是类的具体体现。例如一个Student类,可以创建一个名为“张三”的对象,张三拥有类中所定义的属性,并且可以调用类中所定义的方法。

  • 抽象类与接口
    抽象类:被abstract修饰的类就是抽象类。当父类知道子类一定要完成某种行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。
    抽象类作为父类用来被继承。
    一个类如果继承了抽象类,那么这个类必须重写玩抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
    抽象类的注意事项和特征:
    类有点成员(成员变量,方法,构造器)抽象方法都具备。
    抽象类中可以没有抽象方法,但是有抽象方法的必须是抽象类。
    一个类继承了抽象类必须重写玩抽象类的全部抽象方法,否则这个类必须定义成抽象类。
    不能用abstract修饰变量,代码块,构造器。
    最重要的特征:得到了抽象方法 失去了创建对象的能力(有得有失)
    Final和abstract不能同时用于修饰一个对象
    接口:接口描述的是一组需求,也就是一个类想要符合这个接口就必须满足这些需求,具体来讲就是实现这个接口中的方法。想要某个对象获得某个服务,就必须让该对象所属的类实现对应的接口,也就是该服务需要调用接口中的方法才能给你提供你想要的服务,那么你的类就必须实现这个方法(实现接口),否则没法提供服务。通俗的讲就是你的类必须符合(实现)这个特定的接口,我才能够给你提供服务。
    一个类中所有方法都是抽象方法可以定义成接口。
    接口特性:
    方法都是public方法,默认是public,声明时不要提供。
    接口中没有实例字段(成员变量),但可以包含常量。
    接口之间允许多继承(extends),一个类可以实现多个接口(implements),用逗号分隔多个接口。
    无法通过new运算发构造接口对象实例,但是可以声明接口变量来引用实现该接口的类的对象。
    接口中的字段默认是public static final 修饰。也就是常量。
    接口中可以包含抽象方法和具体实现的方法。
    抽象方法默认是public abstract修饰。
    静态方法可以具体实现,public static 修饰。
    private修饰的方法可以是静态或实例方法,都是具体实现并且只能在接口中使用(private的),作为其他方法的辅助方法。
    私有方法和公共静态方法不能被实现类覆盖。
    default(默认)修饰的方法必须具体实现,默认方法中可以调用其他方法。default方法只能在接口中实现不能被实现类覆盖。
    接口修饰符只有public。
    类的修饰符分为:可访问控制符和非访问控制符两种。
    可访问控制符是:公共类修饰符 public
    非访问控制符有:抽象类修饰符 abstract ;最终类修饰符 final
    属性的控制修饰符也分为:可访问控制符和非访问控制符两类。
    可访问控制符有 4 种:公共访问控制符: public ;私有访问控制符: private ;保护访问控制符: protected ;私有保护访问控制符: private protected
    非访问控制符有 4 种:静态域修饰符: static ;最终域修饰符: final ;易失 ( 共享 ) 域修饰符: volatile ;暂时性域修饰符: transient
    方法的控制修饰符也分为:可访问控制符和非访问控制符两类。
    可访问控制符有 4 种:公共访问控制符: public ;私有访问控制符: private ;保护访问控制符: protected ;私有保护访问控制符: private protected
    非访问控制符有 5 种:抽象方法控制符: abstract ;静态方法控制符: static ;最终方法控制符: final ;本地方法控制符: native ;同步方法控制符: synchronized
    接口中可以定义变量,但是java语法要求:接口中的变量必须使用static和final修饰,同时,其访问控制符必须是public的,总而言之,接口中的变量是静态变量,而且值不能改变。即必须用public,static和final使用。
    借口中只能定义常量,而类中既可以定义类变量和局部变量

  • 关键字
    关键字:电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字,还有特别意义的变量。
    Java中共有48个关键字,分别为:48个关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。
    来自 https://blog.csdn.net/weixin_46822367/article/details/120953556
    this:this指代的是当前类的对象的引用,简单说就是指当前类实列化的对象,而不是指当前类。
    super:super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。super关键字代表父类的引用,所以super关键字也只存在与继承关系中。
    除了Object类之外其他所有类的构造方法第一句总是super(…)
    任何类的构造方法中,若是构造方法的第一行代码没有显式的调用super(…);那么Java默认都会调用super(); 所以你这里的super(); 加不加都无所谓。
    super关键字可以调用父类的属性。
    super关键字可以调用父类的方法。
    super调用父类的构造方法(必须放在首行)。
    final:final的用法
    修饰变量:
    被final修饰的变量不可改变。即初始化一次后,就不能再次被赋值!即,变为常量!
    首先如果这个变量是一个基本数据类型,比如int、String等被final修饰后值就不能改变,这时这个变量就是一个常量;其次如果这个变量是一个引用数据类型,比如数组、集合等被final修饰后这个变量的内存地址的引用不能被修改,但是其本身内部数据是可以改变的,也就是说如果数组、集合被final修饰也可以添加删除数据。
    final修饰的变量必须被初始化
    初始化方法:在声明final变量的同时就赋值,这种方式是最常见的初始化final变量的方式:
    在初始化器中初始化,常见的初始化器如构造函数。我们可以给一个final修饰的变量只声明不赋值,这种变量即为空白变量,之后在构造函数中去初始化这个变量,需要注意的是如果有多个构造函数,那么每个构造函数中都需要初始化一次这个变量,或者通过this调用其他已经初始化过final变量的构造函数,否则编译会报错:
    修饰方法:
    被final修饰的方法不可以被子类重写!
    锁定方法,让此方法不被重写;提高方法运行效率。
    如果一个方法设计得比较完整,不想被子类重写,那么可以用final来修饰这个方法。
    当一个方法被final修饰,那么JVM会针对这个方法的调用转为内联调用,大概意思就是:不采用普通方法那套调用流程,直接把方法展开执行里面的代码,这样在一定程度上节省了调用开销。但是如果一个方法本身含有许多流程代码,那么也达不到节约开销的效果。
    修饰类:
    被final修饰的类不能被继承!
    一个类被final修饰后就是一个不可被继承的类,而且这个类中的所有方法都默认为是final方法,但是变量却不会被默认为final变量。常见的final类如:String、Double、Integer等。
    被final修饰后的类不能扩展功能,所以JVM不在花费开销去关心类的继承,而且由于final类中的方法都默认是final方法,在一定程度上也会节约开销。
    public :public 表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用。
    private :private 表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,子类也不可以。private 不但可以修饰成员变量也可以修饰成员方法。
    Java中引入private的类型,目的是为了防止类中的数据成员,在类的定义之外被修改。也就说,private类型的数据成员只能在定义的时候修改,其余任何地方都不可以,该类的对象也不可以。而且,private类型的数据可以作为构造函数的输入。

  • 方法签名
    方法签名,简单来说就是构成方法的名称,形参顺序和类型组成的,用于确定一个唯一的方法,并且可以确定两个方法是否可以重载。方法签名不包括方法的返回类型。不包括返回值和访问修饰符。
    字码层面的方法签名:方法名称、参数顺序、参数类型、方法返回值、受查异常表。
    代码层面的方法签名:方法名称、参数顺序、参数类型
    一个类中可以有同命的方法。

  • 基本语句
    循环:for循环,while循环,死循环(while(true)),do while循环。
    增强for循环,用于遍历集合的for循环
    判断循环:if语句,if else语句,if else if else语句,switch语句
    跳出循环:一种是常用的break,continue,return方式;

  • 重写与重载
    重载:类内部多态。在一个类的内部如果有多个方法的方法名相同参数列表不同。由类内部多态的定义可知,同一个类中,可以出现相同名称的方法,但是参数列表一定要不同。其中最典型的就是有参和无参的构造方法。
    重载:参数列表:必须修改;返回类型:可以修改;异常:可以修改;访问:可以修改;
    重写:继承中多态。
    重写:参数列表:一定不能修改;返回类型:一定不能修改;异常:可以减少或删除,一定不能抛出新的或者更广的异常;访问:一定不能做更严格的限制(可以降低限制);
    方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
      (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。–>改变躯壳
      (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。–>不改变躯壳,只改变行为
      (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

  • 构造方法
    作用:创建对象;初始化成员变量
    特点:首先是构造方法的方法名要与类名一致构造方法分为:有参构造方法和无参构造方法;构造方法无返回类型,void类型也不可以;构造方法是不能被继承的,但是可以使用super来调用,且super必须声明在在子类构造方法中的首行;默认有一个无参构造方法,当自定义无参构造方法的时候,默认则无效;可以没有构造方法(编译器默认有一个无参构造方法),也可以有多个构造方法,他们之间构成重载关系;
    常用的getter和setter方法。

public class ConstructionDemo6 {
    private String name;
    private int number;
    private double score;
    public ConstructionDemo6(String name, int number, double score) {
        this.name = name;
        this.number = number;
        this.score = score;
    }
    public static void main(String[] args) {
        ConstructionDemo6 construction=new ConstructionDemo6("杜",1,99.9);
        System.out.println("我是"+ construction.name+",我学号是:"+ construction.number+",我这次成绩是:"+ construction.score);
    }
}
  • Java数组
    ava中的数组是对象。在Java编程语言中,数组是动态创建的对象,可以赋值给Object类型的变量。Object类的所有方法都可以在数组上调用。
    数组不是为某个类写的。
    数组本质上就是让我们能"批量"创建相同类型的变量.
    一次性定义N个数据类型相同的变量,我们把这种结构称之为数组
    数组的初始化方式有两种:分别为数组的动态初始化,和数组的静态初始化
    动态初始化:
    第一种:
    //数据类型[] 数组名称 = new 数组类型[] {初始化数据}; ps:初始化数据可选
int[] arr = new int[] {1,2,3,4,5};
//在创建数组时,每个元素同时赋值.

第二种:
//数据类型[] 数组名称 = new 数据类型[num]; num指当前数组元素的最大个数

int[] arr = new int[5]
//在创建数组时,若没有使用来初始化每个元素的值,每个元素都是该数据类型的默认值(0)
//可以理解为	int[] arr = new int[] {0,0,0,0,0};

静态初始化://数据类型[] 数组名称 = {初始化数据};

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

获取数组的长度:使用数组名称.length

int[] arr = new int[5];//长度是5
arr.length;
int[] arr1 = new int[] {1,3,5,7,9};//长度也是5
arr1.length;

访问数组元素:
使用 -> 数组的名称[元素的索引]
//数组的索引从0开始,最后一个元素的索引是 arr1.length - 1
访问不存在的索引时会提示越界

数组遍历用for或者foreach方法

Foreach方法:

        for (int i:arr1) {
            System.out.print(i + ",");
        }

for循环是基于下标(偏移量)来定位的循环。
foreach是基于指针直接移动(地址运算)的循环。
foreach与for循环的明显差别在于:foreach循环时循环对象(数组、集合)被锁定,不能对循环对象中的内容进行增删改操作。

  • 集合框架
    集合框架是一个用来代表和操纵集合的统一架构(java集合框架位于java.util包中)。所有的集合框架都包含如下内容:
    接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
    实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
    算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
    Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。
    集合框架被设计成要满足以下几个目标。
    该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
    该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
    对一个集合的扩展和适应必须是简单的。
    为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。
    Java集合类主要由两个根接口Collection和Map派生出来的。
    Collection接口:List接口(ArrayList类、LinkedList类)、Set接口(HashSet类、TreeSet类)。
    Map接口:HashMap类、TreeMap类、HashTable类
    Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,集合框架中常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
    集合类:
    AbstractCollection
    实现了大部分的集合接口。
    AbstractList
    继承于AbstractCollection 并且实现了大部分List接口。
    AbstractSequentialList
    继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。
    LinkedList
    该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:
    List list=Collections.synchronizedList(newLinkedList(…));
    LinkedList 查找效率低。
    ArrayList
    该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。
    AbstractSet
    继承于AbstractCollection 并且实现了大部分Set接口。
    HashSet
    该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。
    LinkedHashSet
    具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
    TreeSet
    该类实现了Set接口,可以实现排序等功能。
    AbstractMap
    实现了大部分的Map接口。
    HashMap
    HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
    该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
    TreeMap
    继承了AbstractMap,并且使用一颗树。
    WeakHashMap
    继承AbstractMap类,使用弱密钥的哈希表。
    LinkedHashMap
    继承于HashMap,使用元素的自然顺序对元素进行排序.
    IdentityHashMap
    继承AbstractMap类,比较文档时使用引用相等。
    Vector
    该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。
    Stack
    栈是Vector的一个子类,它实现了一个标准的后进先出的栈。
    Dictionary
    Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。
    Hashtable
    Hashtable 是 Dictionary(字典) 类的子类,位于 java.util 包中。
    Properties
    Properties 继承于 Hashtable,表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串。
    BitSet
    一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。

  • ArrayList、HashSet、HashMap的存取及遍历
    ArrayList:
    ArrayList声明:

ArrayList<在这里面限定数据类型> arrayList=new ArrayList();

存入数据直接arrayList.add(要存入的数据);
在在第N个数据后面添加一个数据:

arrayList.add(1,”e”)

将一个ArrayList中的所有数据添加到另外一个ArraList中:

List1.add(list2);

将一个ArrayList中的所有数据添加到另外一个ArraList中的第N个元素之后。

List1.add(1,list2);

ArrayList删除:
按照位置删除:
将list中第2个数据删除

list.remove(2);   位置从0开始计算(0、1、2、3...)

按照内容删除单个数据
将list中的数据"d"删除

list.remove("d");  //对于int,String,char这样的原始类型数据是可以删除的,但是对于复杂对象,例如自己编写的User类、Person类对象,需要重写equals方法,负责remove方法无法匹配删除。

按照集合同时删除多个数据
按照list2中的数据来删除list1

list.removeAll(list2);

清空ArrayList

list.clear();

ArrayList的修改方法
将list中第2个元素,修改为M

list.set(2, "M"); 从0开始计算位置

ArrayList的查询
获取指定位置元素

//获取list中第2个元素
String ele = list.get(2);  位置从0开始计算(0、1、2、3...)

遍历 ArrayList

import java.util.*;
public class test {
    public static void main(String[] args) {
        List list=new ArrayList();
        list.add("Hello");
        list.add("World");
        list.add("Java");
        //第一种遍历方法使用 For-Each 遍历 List 采用ForEach方法遍历
        for (String str : list) {            //也可以改写 for(int i=0;i ite=list.iterator();
        while(ite.hasNext())//判断下一个元素之后有值
        {
            System.out.println(ite.next());
        }
    }
}

HashSet:
HashSet是基于HashMap来实现的,是一个不允许有重复元素的集合。
HashSet允许有null值
HashSet是无序的,即不会记录插入的顺序。
HashSet不是线程安全的,如果多个线程尝试同时修改HashSet,则最终结果是不确定的。
必须在多线程访问时显式同步对HashSet的并发访问。
HashSet实现了Set接口 >Iterable
声明:

HashSet sites= new HashSet();

添加元素:

Sites.add(“a”);
Sites.add(“b”);
Sites.add(“c”);
Sites.add(“d”);

输出:

System.out.println(sites);

判断元素是否存在:

Sites.contains(“xx”);

删除某个:

sites.remove(“xx”);

全部清除:

sites.clear();

计算大小:

sites.size();

遍历foreach方法:

For(String i : sites){
System.out.println(i);
}

遍历Iterator方法

        Iterator iterator = hashSet.iterator();
        while (iterator.hasNext()) {//有值时继续遍历
            Object next = iterator.next();
            System.out.println(next);
        }

HashMap:
HashMap是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。HashMap不会记录插入的顺序,即它是无序的。
HashMap继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap的key与value类型可以相同也可以不同,可以是字符串(String)类型的key和value,也可以是整型(Integer)的key和字符串(String)类型的value。
//导入包

import java.util.HashMap;
 
public class Test{
    public static void main(String[] args){
        //初始化,创建HashMap的对象sites
        //此时sites的key值类型为整型,value类型为字符串类型
        HashMap sites = new HashMap();
        
        //使用put()方法添加键值对Hash MAP添加键值对使用Put方法
        sites.put(1,"red");
        sites.put(2,"blue");
        sites.put(3,"green");
        sites.put(4,"yellow");
        //输出元素
        System.out.println("-----------类型-------------");
        System.out.println(sites);
 
        //类型
        HashMap sites2 = new HashMap();
        //put()添加键值对
        sites2.put("one","red");
        sites2.put("tow","green");
        sites2.put("three","black");
        sites2.put("four","pink");
        //输出元素
        System.out.println("-----------类型-------------");
        System.out.println(sites);
        
        //获取元素
        //使用get(key)方法可以获取key对应的value
        System.out.println(sites.get(3));
 
        //使用remove(key)来删除key对应的键值对(key-value)
        sites.remove(4);
        System.out.println("------------删除第四个元素后----------------");
        System.out.println(sites);
 
        //删除所有键值对可以使用clear方法
        sites.clear();
        System.out.println("------------删除所有元素------------");
        System.out.println(sites);
 
        //要计算元素数量可以使用size()方法
        System.out.println(sites2.size());
 
        //迭代
        for(String i : sites2.keySet()){
            System.out.println("key:"+i+" value:"+sites2.get(i));
        }
 
    }
}

HashMap遍历:

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap Sites = new HashMap();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        // 输出 key 和 value
        for (Integer i : Sites.keySet()) {
            System.out.println("key: " + i + " value: " + Sites.get(i));
        }
        // 返回所有 value 值
        for(String value: Sites.values()) {
          // 输出每一个value
          System.out.print(value + ", ");
        }
    }
}

判断 hashMap 是否为空:

isEmpty()

检查hashMap中是否存在指定的key对应的映射关系:

containsKey()

检查hashMap中是否存在指定的value对应的映射关系:

containsValue()

获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值:

getOrDefault()
  • Lambda表达式
    Lambda 表达式也称为闭包,是Java 8 发布的新特性
    Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)
    为什么要使用Lambda表达式:
    避免匿名内部类定义过多,可以让代码简洁紧凑,留下核心的逻辑
(parameters) -> expression[表达式]
(parameters) -> statements[语句]
(parameters) ->{ statements; }

lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

Lambda表达式实例:

// 1. 不需要参数,返回值为 5  
() -> 5  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

使用Lambda表达式时注意:
Lambda 表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

Lambda表达式优势:
更少的代码行-lambda表达式的最大好处之一就是减少了代码量。我们知道,lambda表达式只能与功能接口一起使用。例如,Runnable 是一个接口,因此我们可以轻松地应用lambda表达式。
通过将行为作为方法中的参数传递来支持顺序和并行执行-通过在Java 8中使用Stream API,将函数传递给collection方法。现在,集合的职责是以顺序或并行的方式处理元素。
更高的效率-过使用Stream API和lambda表达式,可以在批量操作集合的情况下获得更高的效率(并行执行)。 此外,lambda表达式有助于实现集合的内部迭代,而不是外部迭代。

  • 函数式接口
    函数式接口在Java中是指:有且仅有一个抽象方法的接口。 当然接口中可以包含其他的方法(默认,静态,私有)。即其他非函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
    函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
    函数式接口可以被隐式转换为 lambda 表达式。

如定义了一个函数式接口如下:
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}
那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):
GreetingService greetService1 = message -> System.out.println("Hello " + message);

使用@FunctionalInterface可以检测一个接口是不是函数式接口,将@FunctionalInterface放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败。
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
作用:可以检测接口是否是一个函数式接口
是:编译成功 否:编译失败(接口中没有抽象方法或者抽象方法的个数多于一个)
函数式接口的使用:一般作为方法的参数和返回值类型
当参数是一个接口时,我们可以采用下面三种方法来进行操作

@FunctionalInterface
public interfaceSum {
    void show();
}

如果方法的参数提供是一个函数式接口,我们可以使用Lambda表达式做为参数传递

startThread(() -> System.out.println(Thread.currentThread().getName()+"线程启动"))

如果返回值是一个函数式接口,我们可以使用Lambda表示作为结果返回

private static Comparator getComparator(){
        return (s1,s2) -> s1.length()-s1.length();
    }

常用的函数式接口:Supplier,Function,Consumer,Predicate。
Supplier:java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据。
求数组最大值:
使用 Supplier 接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值。提示:接口的泛型请使用 java.lang.Integer 类。

package com.itheima.demo01.Lambda;
import java.util.function.Supplier;
public class Demo02Test {
    //定义一个方法,方法的参数传递Supplier,泛型使用Integer
    public static Integer  getMax(Supplier sup){
        return sup.get();
    }
    public static void main(String[] args) {
        int[] arr={12,9,8,3,30};
        //调用getMax方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
        int maxValue=getMax(()->{
            int max=arr[0];
            for (int i = 0; i 

Consumer:java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据(至于具体怎么消费(使用), 需要自定义(输出,计算…) 其数据类型由泛型决定。
抽象方法:accept
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。基本使用如:

package com.itheima.demo01.Lambda;
import java.util.function.Consumer;
public class Demo03Consumer {
    
    public static void method(String name,Consumer con){
        con.accept(name);
    }
    public static void main(String[] args) {
     //调用method方法,传递字符串姓名,方法的另一个参数是Consumer接口,是一个函数式接口,所以可以传递Lombda表达式
        method("不放弃",(String name)->{
            //1.最简单的消费,直接输出
            System.out.println(name);
            //2.消费方式:把字符串进行翻转输出
            //StringBuffer里面有个字符反转的方法
            String s=new StringBuffer(name).reverse().toString();
            System.out.println(s);
        });
    }
}

默认方法:andThen
如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作,
然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。

package com.itheima.demo01.Lambda;
import java.util.function.Consumer;
public class Demo04 {
    ///定义一个方法,方法的参数传递一个字符串和两个Consumer接口, Consumer接口的泛型使用字符串
    public static void method(String s, Consumer con1,Consumer con2){
       // con1.accept(s);
        //con2.accept(s);
        con1.andThen(con2).accept(s);//con1连接con2,先执行con1消费数据,再执行con2消费数据
    }
    public static void main(String[] args) {
        method("BeiJing",
                (s)->{
                //消费方式:将字符串变成小写
                    System.out.println(s.toLowerCase());
                },
                (s)->{
                 //消费方式:将字符串变成大写
                    System.out.println(s.toUpperCase());
                }
                );
    }
}

Predicate:有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
java.util.function.Predicate 接口。
抽象方法:test
Predicate 接口中包含一个抽象方法: boolean test(T t) 。用于条件判断的场景:

import java.util.function.Predicate; 
public class Demo15PredicateTest { 
    private static void method(Predicate predicate) { 
        boolean veryLong = predicate.test("HelloWorld"); 
        System.out.println("字符串很长吗:" + veryLong); }
    public static void main(String[] args) { 
        method(s ‐> s.length() > 5); 
    }
}

条件判断的标准是传入的Lambda表达式逻辑,只要字符串长度大于5则认为很长。
默认方法:and
相当于&&
既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起来实
现“并且”的效果时,可以使用default方法 and 。
如果要判断一个字符串既要包含大写“H”,又要包含大写“W”,那么:

import java.util.function.Predicate; 
public class Demo16PredicateAnd { 
    private static void method(Predicate one, Predicate two) {
        boolean isValid = one.and(two).test("Helloworld"); 
        System.out.println("字符串符合要求吗:" + isValid); 
    }
    public static void main(String[] args) { 
        method(s ‐> s.contains("H"), s ‐> s.contains("W")); 
    }
}

默认方法:or
与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”。
如果希望实现逻辑“字符串包含大写H或者包含大写W”,那么代码只需要将“and”修改为“or”名称即可,其他都不

import java.util.function.Predicate; 
public class Demo16PredicateAnd { 
    private static void method(Predicate one, Predicate two) { 
        boolean isValid = one.or(two).test("Helloworld"); 
        System.out.println("字符串符合要求吗:" + isValid); 
    }
    public static void main(String[] args) {
        method(s ‐> s.contains("H"), s ‐> s.contains("W"));
    }
}

默认方法:negate
“与”、“或”已经了解了,剩下的“非”(取反)也会简单。
从实现中很容易看出,它是执行了test方法之后,对结果boolean值进行“!”取反而已。一定要在 test 方法调用之前
调用 negate 方法,正如 and 和 or 方法一样:

import java.util.function.Predicate; 
public class Demo17PredicateNegate { 
    private static void method(Predicate predicate) { 
        boolean veryLong = predicate.negate().test("HelloWorld"); 
        System.out.println("字符串很长吗:" + veryLong); 
    }
    public static void main(String[] args) { 
        method(s ‐> s.length() < 5);
    }
}

Function:java.util.function.Function 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,
后者称为后置条件。
抽象方法:apply
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。
使用的场景例如:将 String 类型转换为 Integer 类型。
代码演示:

import java.util.function.Function; 
public class Demo11FunctionApply {
    private static void method(Function function) { 
        int num = function.apply("10");
        System.out.println(num + 20); 
    }
    public static void main(String[] args) { 
        method(s ‐> Integer.parseInt(s));
    }
}
  • 匿名内部类
    使用 Java 编程时,常常需要创建不会被再次使用的对象。在这种情况下,非常适合使用一种特殊的内部类:匿名内部类。这种类没有名称,是在同一条语句中声明和创建的。
    要使用匿名内部类,可将引用对象的代码替换为关键字 new、对构造函数的调用以及用大括号({和})括起的类定义。既然是匿名类,所以你无法在别的地方实例化和使用这个类。匿名内部类也可用于接口(interface)的实现。
    匿名对象:没有名字的对象。
new ClassName().run();

非匿名对象:含有名字的对象。

ClassName c=new ClassName();
c.run();

一般的写法:

ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();

转化成:

Thread runner = new Thread(new Runnable() {
    public void run() {
        // thread does its work here
    }
});
runner.start();

即,这相当于将 Thread(task)的参数task替换成下面的代码实现:

new Runnable() {
    public void run() {
        // thread does its work here
    }
}

匿名内部类的另一种写法

new 类名或者接口名() {
    重写方法;
}
var t = new Thread() {
    public void run() {
        这是被重写的方法;
    }
}
  • 注解
    Annotation(注解)是JDK5开始引入的新特性,可以看作是一种特殊的注释,主要用于修饰类,方法或者变量,在框架中大量使用(如 Spring、Mybatis等)。
    注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。
    ​ 注解只有被解析之后才会生效,常见的解析方法有两种:
    编译期间直接扫描:编译器在编译Java代码的时候扫描对于的注解并处理,比如某个方法使用了@Override,编译器在编译的时候就会检测当前的方法是否重写了父类对于的方法。
    运行期间通过反射处理:这个经常在Spring框架中看到,例如Spring的@Value注解,就是通过反射来进行处理的。
    元注解:​ JDK1.8版本为我们提供了6个标准的用来对注解类型进行注解的注解类(1.8之前只有四个),我们称之为meta-annotation(元注解)。
    元注解只能用在注解之上(自定义注解时可用)
    @Target
	指示注解类型适用的上下文。注解类型可能适用的声明上下文和类型上下文在 JLS 9.6.4.1 中指定,并在源代码中由java.lang.annotation.ElementType的枚举常量表示。
	如果注解类型T上不存在@Target元注解,则类型T的注解可以写为除类型参数声明之外的任何声明的修饰符。
	如果存在@Target元注解,编译器将强制执行ElementType枚举常量指示的使用限制,符合 JLS 9.7.4。

@Retention

指示要保留带注解类型的注解多长时间。如果注释类型声明中不存在保留注释,则保留策略默认为RetentionPolicy.CLASS 。
仅当元注释类型直接用于注释时,保留元注释才有效。如果将元注释类型用作另一个注释类型中的成员类型,则它没有效果。

@Documented

表示默认情况下,带有类型的注释将由 javadoc 和类似工具记录。这种类型应该用于注解类型的声明,这些类型的注释会影响其客户对注释元素的使用。如果使用 Documented 对类型声明进行注释,则其注释将成为注释元素的公共 API 的一部分。

@Inherited

指示注解类型是自动继承的。如果注解类型声明中存在 Inherited 元注解,并且用户在类声明中查询注解类型,并且类声明没有该类型的注解,则将自动查询该类的超类以获取注解类型。将重复此过程,直到找到此类型的注释,或到达类层次结构(对象)的顶部。如果没有超类具有此类型的注释,则查询将指示所讨论的类没有此类注释。
请注意,如果注释类型用于注释类以外的任何内容,则此元注释类型无效。另请注意,此元注释仅导致注释从超类继承;已实现接口上的注解无效。

@Native(1.8新增)

表示可以从本机代码引用定义常量值的字段。注释可以被生成本机头文件的工具用作提示,以确定是否需要头文件,如果需要,它应该包含哪些声明。

@Repeatable(1.8新增)

注释类型java.lang.annotation.Repeatable用于指示它(元)注释其声明的注释类型是可重复的。 @Repeatable的值表示可重复注解类型的包含注解类型。

JDK基本注解介绍
基本注解包括
@Override

指示方法声明旨在覆盖超类型中的方法声明。如果使用此注解类型对方法进行注解,则编译器需要生成错误消息,除非至少满足以下条件之一:
该方法确实覆盖或实现了在超类型中声明的方法。
该方法的签名与Object中声明的任何公共方法的签名等效。

@Deprecated

@Deprecated 注释的程序元素是不鼓励程序员使用的程序元素,通常是因为它很危险,或者因为存在更好的替代方案。当在非弃用代码中使用或覆盖弃用的程序元素时,编译器会发出警告。

@SuppressWarnings

指示应在带注释的元素(以及带注释的元素中包含的所有程序元素)中抑制命名的编译器警告。请注意,给定元素中抑制的警告集是所有包含元素中抑制的警告的超集。例如,如果您注释一个类以抑制一个警告并注释一个方法以抑制另一个警告,则两个警告都将在方法中被抑制。
作为风格问题,程序员应该始终在最有效的嵌套元素上使用此注释。如果您想在特定方法中抑制警告,您应该注释该方法而不是它的类。

@SafeVarargs

程序员断言带注释的方法或构造函数的主体不会对其 varargs 参数执行潜在的不安全操作。将此注释应用于方法或构造函数会抑制有关不可具体化的变量 arity (vararg) 类型的未经检查的警告,并抑制有关在调用站点创建参数化数组的未经检查的警告。
除了@Target元注解施加的使用限制外,编译器还需要对该注解类型实施额外的使用限制;如果使用@SafeVarargs注释对方法或构造函数声明进行注释,则这是编译时错误,并且:
声明是一个固定的arity方法或构造函数
声明是一个既不是static也不是final的变量 arity 方法。
鼓励编译器在将此注释类型应用于方法或构造函数声明时发出警告,其中:
变量 arity 参数具有可具体化的元素类型,包括原始类型、 Object和String 。 (对于可具体化的元素类型,此注释类型抑制的未经检查的警告已经不会出现。)
方法或构造函数声明的主体执行潜在的不安全操作,例如对变量 arity 参数数组的元素的赋值会生成未经检查的警告。一些不安全的操作不会触发未经检查的警告。例如,别名在
   @SafeVarargs // 实际上并不安全!
   static void m(List... stringLists) {
     Object[] array = stringLists;
     List tmpList = Arrays.asList(42);
     array[0] = tmpList; // 语义上无效,但可以编译
     String s = stringLists[0].get(0); // 哦不,运行时的 ClassCastException!
   }
   
在运行时导致ClassCastException 。
该平台的未来版本可能会要求此类不安全操作出现编译器错误。

@FunctionalInterface

一种信息性注解类型,用于指示接口类型声明旨在成为 Java 语言规范定义的功能接口。从概念上讲,函数式接口只有一个抽象方法。由于默认方法有一个实现,它们不是抽象的。如果接口声明了一个覆盖java.lang.Object的公共方法之一的抽象方法,这也不会计入接口的抽象方法计数,因为接口的任何实现都将具有来自java.lang.Object或其他地方的实现(接口的实现是类,所有类的父类都是Object)。
请注意,函数式接口的实例可以使用 lambda 表达式、方法引用或构造函数引用来创建。
如果使用此注解类型对类型进行注解,则编译器需要生成错误消息,除非:
该类型是接口类型,而不是注解类型、枚举或类。
带注解的类型满足功能接口的要求。
但是,无论接口声明中是否存在FunctionalInterface注释,编译器都会将满足功能接口定义的任何接口视为功能接口。

来源https://blog.csdn.net/D1842501760/article/details/124042500

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1027737.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号