精华内容
下载资源
问答
  • Java基础知识点总结归纳,超级全面!(2021版)

    千次阅读 多人点赞 2021-05-03 12:18:04
    所以今天花了一天时间整理了一份Java基础知识点总结归纳,超级全面!希望对大家有帮助哈~ 由于本文篇幅过长,博主为了方便大家阅读和收藏,特意将本文转成了一份PDF版的文档。 需要PDF版的朋友可以关注微信公众号...

    凯哥今天看了网上好多关于Java基础知识点汇总的博客,but,感觉都不尽如人意,要么不全面,要么不准确,要么排版太乱了!

    所以今天花了一天时间整理了一份Java基础知识点总结归纳,超级全面!希望对大家有帮助哈~

    由于本文篇幅过长,博主为了方便大家阅读和收藏,特意将本文转成了一份PDF版的文档。

    需要PDF版的朋友可以关注微信公众号:Java团长,发送“ 基础知识 ”即可获取哈~

    一、Java概述

    1、何为编程

    编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。

    为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

    2、什么是Java

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。

    3、jdk1.5之后的三大版本

    Java SE(J2SE,Java 2 Platform Standard Edition,标准版)
    Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为Java EE和Java ME提供基础。

    Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)
    Java EE 以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0应用程序。2018年2月,Eclipse 宣布正式将 JavaEE 更名为 JakartaEE

    Java ME(J2ME,Java 2 Platform Micro Edition,微型版)
    Java ME 以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

    4、JVM、JRE和JDK的关系

    JVM
    Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

    JRE
    Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包

    如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

    JDK
    Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等

    JVM&JRE&JDK关系图:

    5、什么是跨平台性?原理是什么

    所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。

    实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。

    6、Java语言有哪些特点

    简单易学(Java语言的语法与C语言和C++语言很接近)

    面向对象(封装,继承,多态)

    平台无关性(Java虚拟机实现平台无关性)

    支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)

    支持多线程(多线程机制使应用程序在同一时间并行执行多项任)

    健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)

    安全性

    7、什么是字节码?采用字节码的最大好处是什么

    字节码:Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。

    采用字节码的好处:

    Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

    先看下java中的编译器和解释器:

    Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。

    Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。

    8、什么是Java程序的主类?应用程序和小程序的主类有何不同?

    一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。

    9、Java应用程序与小程序之间有那些差别?

    简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。

    10、Java和C++的区别

    我知道很多人没学过C++,但是面试官就是没事喜欢拿咱们Java和C++比呀!没办法!!!就算没学过C++,也要记下来!

    • 都是面向对象的语言,都支持封装、继承和多态
    • Java不提供指针来直接访问内存,程序内存更加安全
    • Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
    • Java有自动内存管理机制,不需要程序员手动释放无用内存

    11、Oracle JDK 和 OpenJDK 的对比

    1. Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
    2. OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;
    3. Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
    4. 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
    5. Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
    6. Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。

    二、基础语法

    1、数据类型

    1. Java有哪些数据类型

    定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。

    分类

    • 基本数据类型
      • 数值型
        • 整数类型(byte,short,int,long)
        • 浮点类型(float,double)
      • 字符型(char)
      • 布尔型(boolean)
    • 引用数据类型
      • 类(class)
      • 接口(interface)
      • 数组([])

    Java基本数据类型图

    2. switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上

    在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

    3. 用最有效率的方法计算 2 乘以 8

    2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。

    4. Math.round(11.5) 等于多少?Math.round(-11.5)等于多少

    Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加 0.5 然后进行下取整。

    5. float f=3.4;是否正确

    不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。

    6. short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗

    对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。

    而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

    2、编码

    Java语言采用何种编码方案?有何特点?

    Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

    3、注释

    1. 什么Java注释

    定义:用于解释说明程序的文字

    分类

      • 单行注释
        格式: // 注释文字
      • 多行注释
        格式: /* 注释文字 */
      • 文档注释
        格式:/** 注释文字 */

    作用

    在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,注释的部分不会对程序的执行结果产生任何影响。

    注意事项:多行和文档注释都不能嵌套使用。

    4、访问修饰符

    1. 访问修饰符 public,private,protected,以及不写(默认)时的区别

    定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

    分类

    private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
    default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
    protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
    public : 对所有类可见。使用对象:类、接口、变量、方法

    访问修饰符图

    5、运算符

    &和&&的区别

    &运算符有两种用法:(1)按位与;(2)逻辑与。

    &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。

    注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

    6、关键字

    1. Java 有没有 goto

    goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。

    2. final 有什么用?

    用于修饰类、属性和方法;

    • 被final修饰的类不可以被继承
    • 被final修饰的方法不可以被重写
    • 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的

    3. final finally finalize区别

    • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
    • finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
    • finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。

    4. this关键字的用法

    this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

    this的用法在java中大体可以分为3种:

    ①. 普通的直接引用,this相当于是指向当前对象本身。

    ②. 形参与成员名字重名,用this来区分:

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    ③. 引用本类的构造函数

    class Person{
        private String name;
        private int age;
        
        public Person() {
        }
     
        public Person(String name) {
            this.name = name;
        }
        public Person(String name, int age) {
            this(name);
            this.age = age;
        }
    }

     

    5. super关键字的用法

    super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

    super也有三种用法:

    ①. 普通的直接引用

    与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。

    ②. 子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

    class Person{
        protected String name;
     
        public Person(String name) {
            this.name = name;
        }
     
    }
     
    class Student extends Person{
        private String name;
     
        public Student(String name, String name1) {
            super(name);
            this.name = name1;
        }
     
        public void getInfo(){
            System.out.println(this.name);      //Child
            System.out.println(super.name);     //Father
        }
     
    }
    
    public class Test {
        public static void main(String[] args) {
           Student s1 = new Student("Father","Child");
           s1.getInfo();
     
        }
    }

    ③. 引用父类构造函数

    • super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
    • this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

    6. this与super的区别

    • super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
    • this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
    • super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
    • super()和this()均需放在构造方法内第一行。
    • 尽管可以用this调用一个构造器,但却不能调用两个。
    • this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
    • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
    • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

    7. static存在的主要意义

    static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!

    static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

    为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    8. static的独特之处

    • 被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。

    怎么理解 “被类的实例对象所共享” 这句话呢?就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我觉得我已经讲的很通俗了,你明白了咩?

    • 在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
    • static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
    • 被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

    9. static应用场景

    因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。

    因此比较常见的static应用场景有:

    • 修饰成员变量
    • 修饰成员方法
    • 静态代码块
    • 修饰类【只能修饰内部类也就是静态内部类】
    • 静态导包

    10. static注意事项

    1. 静态只能访问静态。
    2. 非静态既可以访问非静态的,也可以访问静态的。

    7、流程控制语句

    1. break ,continue ,return 的区别及作用

    break 跳出总上一层循环,不再执行循环(结束当前的循环体)

    continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)

    return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)

    2. 在 Java 中,如何跳出当前的多重嵌套循环

    在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:

    public static void main(String[] args) {
        ok:
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.println("i=" + i + ",j=" + j);
                if (j == 5) {
                    break ok;
                }
    
            }
        }
    }

    三、面向对象

    1、面向对象概述

    面向对象和面向过程的区别

    面向过程:

    优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

    缺点:没有面向对象易维护、易复用、易扩展

    面向对象:

    优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

    缺点:性能比面向过程低

    面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。

    面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。

    面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象了。

    2、面向对象三大特性

    1. 面向对象的特征有哪些方面

    面向对象的特征主要有以下几个方面:

    抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

    封装

    封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。

    继承

    继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

    关于继承如下 3 点请记住:

    1. 子类拥有父类非 private 的属性和方法。
    2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
    3. 子类可以用自己的方式实现父类的方法。(以后介绍)。

    多态

    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

    在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

    其中Java 面向对象编程三大特性:封装 继承 多态

    封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。

    继承:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承可以提高代码复用性。继承是多态的前提。

    关于继承如下 3 点请记住:

    1. 子类拥有父类非 private 的属性和方法。

    2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

    3. 子类可以用自己的方式实现父类的方法。

    多态性:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

    在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

    方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

    一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:

    • 方法重写(子类继承父类并重写父类中已有的或抽象的方法);
    • 对象造型(用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

    2. 什么是多态机制?Java语言是如何实现多态的?

    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

    多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

    多态的实现

    Java实现多态有三个必要条件:继承、重写、向上转型。

    继承:在多态中必须存在有继承关系的子类和父类。

    重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

    向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

    只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。

    对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

    3. 面向对象五大基本原则是什么(可选)

    • 单一职责原则SRP(Single Responsibility Principle)

    类的功能要单一,不能包罗万象,跟杂货铺似的。

    • 开放封闭原则OCP(Open-Close Principle)

    一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。

    • 里式替换原则LSP(the Liskov Substitution Principle LSP)

    子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~

    • 依赖倒置原则DIP(the Dependency Inversion Principle DIP)

    高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。

    • 接口分离原则ISP(the Interface Segregation Principle ISP)

    设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。

    3、类与接口

    1. 抽象类和接口的对比

    抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。

    从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

    相同点

    接口和抽象类都不能实例化
    都位于继承的顶端,用于被其他实现或继承
    都包含抽象方法,其子类都必须覆写这些抽象方法

    不同点

    备注:Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。

    现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它。

    接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:

    • 行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
    • 选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。

    2. 普通类和抽象类有哪些区别?

    • 普通类不能包含抽象方法,抽象类可以包含抽象方法。
    • 抽象类不能直接实例化,普通类可以直接实例化。

    3. 抽象类能使用 final 修饰吗?

    不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类

    4. 创建一个对象用什么关键字?对象实例与对象引用有何不同?

    new关键字,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)

    4、变量与方法

    1. 成员变量与局部变量的区别有哪些

    变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域

    成员变量:方法外部,类内部定义的变量

    局部变量:类的方法中的变量。

    成员变量和局部变量的区别

    作用域

    成员变量:针对整个类有效。
    局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

    存储位置

    成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
    局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。

    生命周期

    成员变量:随着对象的创建而存在,随着对象的消失而消失
    局部变量:当方法调用完,或者语句结束后,就自动释放。

    初始值

    成员变量:有默认初始值。

    局部变量:没有默认初始值,使用前必须赋值。

    使用原则

    在使用变量时需要遵循的原则为:就近原则
    首先在局部范围找,有就使用;接着在成员位置找。

    2. 在Java中定义一个不做事且没有参数的构造方法的作用

    Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

    3. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

    帮助子类做初始化工作。

    4. 一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?

    主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

    5. 构造方法有哪些特性?

    名字与类名相同;

    没有返回值,但不能用void声明构造函数;

    生成类的对象时自动执行,无需调用。

    6. 静态变量和实例变量区别

    静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

    实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

    7. 静态变量与普通变量区别

    static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

    还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。

    8. 静态方法和实例方法有何不同?

    静态方法和实例方法的区别主要体现在两个方面:

    1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
    2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

    9. 在一个静态方法内调用一个非静态成员为什么是非法的?

    由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

    10. 什么是方法的返回值?返回值的作用是什么?

    方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!

    5、内部类

    1. 什么是内部类?

    在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。

    2. 内部类的分类有哪些

    内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。

    静态内部类

    定义在类内部的静态类,就是静态内部类。

    public class Outer {
    
        private static int radius = 1;
    
        static class StaticInner {
            public void visit() {
                System.out.println("visit outer static  variable:" + radius);
            }
        }
    }

     

    静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;静态内部类的创建方式,new 外部类.静态内部类(),如下:

    Outer.StaticInner inner = new Outer.StaticInner();
    inner.visit();

    成员内部类

    定义在类内部,成员位置上的非静态类,就是成员内部类。

    public class Outer {
    
        private static  int radius = 1;
        private int count =2;
        
         class Inner {
            public void visit() {
                System.out.println("visit outer static  variable:" + radius);
                System.out.println("visit outer   variable:" + count);
            }
        }
    }

     

    成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有。成员内部类依赖于外部类的实例,它的创建方式外部类实例.new 内部类(),如下:

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();
    inner.visit();

    局部内部类

    定义在方法中的内部类,就是局部内部类。

    public class Outer {
    
        private  int out_a = 1;
        private static int STATIC_b = 2;
    
        public void testFunctionClass(){
            int inner_c =3;
            class Inner {
                private void fun(){
                    System.out.println(out_a);
                    System.out.println(STATIC_b);
                    System.out.println(inner_c);
                }
            }
            Inner  inner = new Inner();
            inner.fun();
        }
        public static void testStaticFunctionClass(){
            int d =3;
            class Inner {
                private void fun(){
                    // System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量
                    System.out.println(STATIC_b);
                    System.out.println(d);
                }
            }
            Inner  inner = new Inner();
            inner.fun();
        }
    }

    定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部内部类的创建方式,在对应方法内,new 内部类(),如下:

     public static void testStaticFunctionClass(){
        class Inner {
        }
        Inner  inner = new Inner();
     }

    匿名内部类

    匿名内部类就是没有名字的内部类,日常开发中使用的比较多。

    public class Outer {
    
        private void test(final int i) {
            new Service() {
                public void method() {
                    for (int j = 0; j < i; j++) {
                        System.out.println("匿名内部类" );
                    }
                }
            }.method();
        }
     }
     //匿名内部类必须继承或实现一个已有的接口 
     interface Service{
        void method();
    }

    除了没有名字,匿名内部类还有以下特点:

    • 匿名内部类必须继承一个抽象类或者实现一个接口。
    • 匿名内部类不能定义任何静态成员和静态方法。
    • 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。
    • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

    匿名内部类创建方式:

    new 类/接口{ 
      //匿名内部类实现部分
    }

    3. 内部类的优点

    我们为什么要使用内部类呢?因为它有以下优点:

    • 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
    • 内部类不为同一包的其他类所见,具有很好的封装性;
    • 内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
    • 匿名内部类可以很方便的定义回调。

    4. 内部类有哪些应用场景

    1. 一些多算法场合
    2. 解决一些非面向对象的语句块。
    3. 适当使用内部类,使得代码更加灵活和富有扩展性。
    4. 当某个类除了它的外部类,不再被其他的类使用时。

    5. 局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?

    局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final呢?它内部原理是什么呢?

    先看这段代码:

    public class Outer {
    
        void outMethod(){
            final int a =10;
            class Inner {
                void innerMethod(){
                    System.out.println(a);
                }
    
            }
        }
    }

    以上例子,为什么要加final呢?是因为生命周期不一致, 局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。

    6. 内部类相关,看程序说出运行结果

    public class Outer {
        private int age = 12;
    
        class Inner {
            private int age = 13;
            public void print() {
                int age = 14;
                System.out.println("局部变量:" + age);
                System.out.println("内部类变量:" + this.age);
                System.out.println("外部类变量:" + Outer.this.age);
            }
        }
    
        public static void main(String[] args) {
            Outer.Inner in = new Outer().new Inner();
            in.print();
        }
    
    }

    运行结果:

    局部变量:14
    内部类变量:13
    外部类变量:12

    6、重写与重载

    1. 构造器(constructor)是否可被重写(override)

    构造器不能被继承,因此不能被重写,但可以被重载。

    2. 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

    方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

    重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分

    重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。

    7、对象相等判断

    1. == 和 equals 的区别是什么

    == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

    equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

    情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。

    情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

    举个例子:

    public class test1 {
        public static void main(String[] args) {
            String a = new String("ab"); // a 为一个引用
            String b = new String("ab"); // b为另一个引用,对象的内容一样
            String aa = "ab"; // 放在常量池中
            String bb = "ab"; // 从常量池中查找
            if (aa == bb) // true
                System.out.println("aa==bb");
            if (a == b) // false,非同一对象
                System.out.println("a==b");
            if (a.equals(b)) // true
                System.out.println("aEQb");
            if (42 == 42.0) { // true
                System.out.println("true");
            }
        }
    }

    说明:

    String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
    当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。

    2. hashCode 与 equals (重要)

    HashSet如何检查重复

    两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

    hashCode和equals方法的关系

    面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”

    hashCode()介绍

    hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。

    散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

    为什么要有 hashCode

    我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode:

    当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

    hashCode()与equals()的相关规定

    如果两个对象相等,则hashcode一定也是相同的

    两个对象相等,对两个对象分别调用equals方法都返回true

    两个对象有相同的hashcode值,它们也不一定是相等的

    因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖

    hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

    8、值传递

    1. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递

    是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的

    2. 为什么 Java 中只有值传递

    首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。 它用来描述各种程序设计语言(不只是Java)中方法参数传递方式。

    Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。

    下面通过 3 个例子来给大家说明

    example 1

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;
    
        swap(num1, num2);
    
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);
    }
    
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }

    结果:

    a = 20
    b = 10
    num1 = 10
    num2 = 20

    解析:

    img

    在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。

    通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看 example2.

    example 2

        public static void main(String[] args) {
            int[] arr = { 1, 2, 3, 4, 5 };
            System.out.println(arr[0]);
            change(arr);
            System.out.println(arr[0]);
        }
    
        public static void change(int[] array) {
            // 将数组的第一个元素变为0
            array[0] = 0;
        }

    结果:

    1
    0

    解析:

    img

    array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。

    通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。

    很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题。

    example 3

    public class Test {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Student s1 = new Student("小张");
            Student s2 = new Student("小李");
            Test.swap(s1, s2);
            System.out.println("s1:" + s1.getName());
            System.out.println("s2:" + s2.getName());
        }
    
        public static void swap(Student x, Student y) {
            Student temp = x;
            x = y;
            y = temp;
            System.out.println("x:" + x.getName());
            System.out.println("y:" + y.getName());
        }
    }

     

    结果:

    x:小李
    y:小张
    s1:小张
    s2:小李

    解析:

    交换之前:

    img

    交换之后:

    img

    通过上面两张图可以很清晰的看出: 方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝

    总结

    Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。

    下面再总结一下Java中方法参数的使用情况:

    • 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型》
    • 一个方法可以改变一个对象参数的状态。
    • 一个方法不能让对象参数引用一个新的对象。

    3. 值传递和引用传递有什么区别

    值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

    引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

    9、Java包

    1. JDK 中常用的包有哪些

    • java.lang:这个是系统的基础类;
    • java.io:这里面是所有输入输出有关的类,比如文件操作等;
    • java.nio:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包;
    • java.net:这里面是与网络有关的类;
    • java.util:这个是系统辅助类,特别是集合类;
    • java.sql:这个是数据库操作的类。

    2. import java和javax有什么区别

    刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移,javax 逐渐的扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包将是太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。

    所以,实际上java和javax没有区别。这都是一个名字。

    四、IO流

    1、java 中 IO 流分为几种?

    • 按照流的流向分,可以分为输入流和输出流;
    • 按照操作单元划分,可以划分为字节流和字符流;
    • 按照流的角色划分为节点流和处理流。

    Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。

    • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
    • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

    按操作方式分类结构图:

    IO-操作方式分类

    按操作对象分类结构图:

    IO-操作对象分类

    2、BIO,NIO,AIO 有什么区别?

    简答

    • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
    • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
    • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

    详细回答

    • BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
    • NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
    • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

    3、Files的常用方法都有哪些?

    • Files. exists():检测文件路径是否存在。
    • Files. createFile():创建文件。
    • Files. createDirectory():创建文件夹。
    • Files. delete():删除一个文件或目录。
    • Files. copy():复制文件。
    • Files. move():移动文件。
    • Files. size():查看文件个数。
    • Files. read():读取文件。
    • Files. write():写入文件。

    五、反射

    1、什么是反射机制?

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    静态编译和动态编译

    静态编译:在编译时确定类型,绑定对象
    动态编译:运行时确定类型,绑定对象

    2、反射机制优缺点

    • 优点: 运行期类型的判断,动态加载类,提高代码灵活度。
    • 缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

    3、 反射机制的应用场景有哪些?

    反射是框架设计的灵魂。

    在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。

    举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这个字符串获得某个类的Class实例; 4)动态配置实例的属性

    4、Java获取反射的三种方法

    1.通过new对象实现反射机制

    2.通过路径实现反射机制

    3.通过类名实现反射机制

     

    public class Student {
        private int id;
        String name;
        protected boolean sex;
        public float score;
    }
    
    public class Get {
        //获取反射机制三种方式
        public static void main(String[] args) throws ClassNotFoundException {
            //方式一(通过建立对象)
            Student stu = new Student();
            Class classobj1 = stu.getClass();
            System.out.println(classobj1.getName());
            //方式二(所在通过路径-相对路径)
            Class classobj2 = Class.forName("fanshe.Student");
            System.out.println(classobj2.getName());
            //方式三(通过类名)
            Class classobj3 = Student.class;
            System.out.println(classobj3.getName());
        }
    }

    六、网络编程

    网络编程的可以查看这篇文章:https://thinkwon.blog.csdn.net/article/details/104390612

    内容不仅包括TCP/IP协议和三次握手四次挥手的知识,还包括计算机网络体系结构,HTTP协议,get请求和post请求区别,session和cookie的区别等,欢迎大家阅读。

    七、常用API

    1、String相关

    1. 字符型常量和字符串常量的区别

    • 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
    • 含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)
    • 占内存大小:字符常量只占一个字节 字符串常量占若干个字节(至少一个字符结束标志)

    2. 什么是字符串常量池?

    字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

    3. String 是最基本的数据类型吗?

    不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

    这是很基础的东西,但是很多初学者却容易忽视,Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};

    但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。

    4. String有哪些特性

    不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。

    常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。

    final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。

    5. String为什么是不可变的吗?

    简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下图所以:

    /** The value is used for character storage. */
    private final char value[];

    6. String真的是不可变的吗?

    我觉得如果别人问这个问题的话,回答不可变就可以了。 下面只是给大家看两个有代表性的例子:

    1) String不可变但不代表引用不可以变

    String str = "Hello";
    str = str + " World";
    System.out.println("str=" + str);

    结果:

    str=Hello World

    解析:

    实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。

    2) 通过反射是可以修改所谓的“不可变”对象

    // 创建字符串"Hello World", 并赋给引用s
    String s = "Hello World";
    
    System.out.println("s = " + s); // Hello World
    
    // 获取String类中的value字段
    Field valueFieldOfString = String.class.getDeclaredField("value");
    
    // 改变value属性的访问权限
    valueFieldOfString.setAccessible(true);
    
    // 获取s对象上的value属性的值
    char[] value = (char[]) valueFieldOfString.get(s);
    
    // 改变value所引用的数组中的第5个字符
    value[5] = '_';
    
    System.out.println("s = " + s); // Hello_World

     

    结果:

    s = Hello World
    s = Hello_World

    解析:

    用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。

    7. 是否可以继承 String 类

    String 类是 final 类,不可以被继承。

    8. String str="i"与 String str=new String(“i”)一样吗?

    不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

    9. String s = new String(“xyz”);创建了几个字符串对象

    两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。

    String str1 = "hello"; //str1指向静态区
    String str2 = new String("hello");  //str2指向堆上的对象
    String str3 = "hello";
    String str4 = new String("hello");
    System.out.println(str1.equals(str2)); //true
    System.out.println(str2.equals(str4)); //true
    System.out.println(str1 == str3); //true
    System.out.println(str1 == str2); //false
    System.out.println(str2 == str4); //false
    System.out.println(str2 == "hello"); //false
    str2 = str1;
    System.out.println(str2 == "hello"); //true

    10. 如何将字符串反转?

    使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

    示例代码:

    // StringBuffer reverse
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer. append("abcdefg");
    System. out. println(stringBuffer. reverse()); // gfedcba
    // StringBuilder reverse
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder. append("abcdefg");
    System. out. println(stringBuilder. reverse()); // gfedcba

     

    11. 数组有没有 length()方法?String 有没有 length()方法

    数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

    12. String 类的常用方法都有那些?

    • indexOf():返回指定字符的索引。
    • charAt():返回指定索引处的字符。
    • replace():字符串替换。
    • trim():去除字符串两端空白。
    • split():分割字符串,返回一个分割后的字符串数组。
    • getBytes():返回字符串的 byte 类型数组。
    • length():返回字符串长度。
    • toLowerCase():将字符串转成小写字母。
    • toUpperCase():将字符串转成大写字符。
    • substring():截取字符串。
    • equals():字符串比较。

    13. 在使用 HashMap 的时候,用 String 做 key 有什么好处?

    HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

    14. String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的

    可变性

    String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。

    线程安全性

    String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

    性能

    每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

    对于三者使用的总结

    如果要操作少量的数据用 = String

    单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

    多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

    2、Date相关

    3、包装类相关

    1. 自动装箱与拆箱

    装箱:将基本类型用它们对应的引用类型包装起来;

    拆箱:将包装类型转换为基本数据类型;

    2. int 和 Integer 有什么区别

    Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是 Integer,从 Java 5 开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

    Java 为每个原始类型提供了包装类型:

    原始类型: boolean,char,byte,short,int,long,float,double

    包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

    3. Integer a= 127 与 Integer b = 127相等吗?

    对于对象引用类型:==比较的是对象的内存地址。
    对于基本数据类型:==比较的是值。

    如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false

    public static void main(String[] args) {
        Integer a = new Integer(3);
        Integer b = 3;  // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b); // false 两个引用没有引用同一对象
        System.out.println(a == c); // true a自动拆箱成int类型再和c比较
        System.out.println(b == c); // true
    
        Integer a1 = 128;
        Integer b1 = 128;
        System.out.println(a1 == b1); // false
    
        Integer a2 = 127;
        Integer b2 = 127;
        System.out.println(a2 == b2); // true
    }

     

    八、常用工具类库
    九、单元测试
    十、日志

    Java基础知识点总结归纳,超级全面!(2021版)到这里就要跟大家说再见了,本文会不断更新完善,希望老铁们多多关注哦~

    展开全文
  • Java所有的流类位于http://java.io包中,都分别继承字以下四种抽象流类型。 继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit)。 继承自Reader/Writer的流都是...

    一、流

    Java所有的流类位于http://java.io包中,都分别继承字以下四种抽象流类型。

    继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit)。

    继承自Reader/Writer的流都是用于向程序中输入/输出数据,且数据的单位都是字符(2byte=16bit)。

    二、异常

    Java的异常(包括ExceptionError)分为:

    • 可查的异常(checked exceptions)

    除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

    • 不可查的异常(unchecked exceptions)

    包括运行时异常(RuntimeException与其子类)和错误(Error)。

    运行时异常和非运行时异常:

    • RuntimeException

    NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

    • RuntimeException以外的Exception

    从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

    三、注解

    Java SE5内置了三种标准注解:

     @Override,表示当前的方法定义将覆盖超类中的方法。
    
     @Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。
    
     @SuppressWarnings,关闭不当编译器警告信息。
    
    

    Java还提供了4中注解,专门负责新注解的创建:

    • @Target:

    表示该注解可以用于什么地方,可能的ElementType参数有:
    CONSTRUCTOR:构造器的声明
    FIELD:域声明(包括enum实例)
    LOCAL_VARIABLE:局部变量声明
    METHOD:方法声明
    PACKAGE:包声明
    PARAMETER:参数声明
    TYPE:类、接口(包括注解类型)或enum声明

    • @Retention

    表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
    SOURCE:注解将被编译器丢弃
    CLASS:注解在class文件中可用,但会被VM丢弃
    RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息

    • @Document

    将注解包含在Javadoc中

    • @Inherited

    允许子类继承父类中的注解

    Example

    定义注解:

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface UseCase {
        public String id();
        public String description() default "no description";
    }
    

    使用注解:

    public class PasswordUtils {
         @UseCase(id = 47, description = "Passwords must contain at least one numeric")
         public boolean validatePassword(String password) {
             return (password.matches("\\w*\\d\\w*"));
         }
    
         @UseCase(id = 48)
         public String encryptPassword(String password) {
             return new StringBuilder(password).reverse().toString();
         }
     }
    

    解析注解:

    public static void main(String[] args) {
         List<Integer> useCases = new ArrayList<Integer>();
         Collections.addAll(useCases, 47, 48, 49, 50);
         trackUseCases(useCases, PasswordUtils.class);
     }
    
     public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
         for (Method m : cl.getDeclaredMethods()) {
             UseCase uc = m.getAnnotation(UseCase.class);
             if (uc != null) {
                 System.out.println("Found Use Case:" + uc.id() + " "
                             + uc.description());
                 useCases.remove(new Integer(uc.id()));
             }
         }
         for (int i : useCases) {
             System.out.println("Warning: Missing use case-" + i);
         }
     }
     // Found Use Case:47 Passwords must contain at least one numeric
     // Found Use Case:48 no description
     // Warning: Missing use case-49
     // Warning: Missing use case-50
    

    四、安全性

    1. 严格遵循面向对象的规范。这样封装了数据细节,只提供接口给用户。增加了数据级的安全性。

    2. 无指针运算。java中的操作,除了基本类型都是引用的操作。引用是不能进行增减运算,不能被直接赋予内存地址的,从而增加了内存级的安全性。

    3. 数组边界检查。这样就不会出现C/C++中的缓存溢出等安全漏洞。

    4. 强制类型转换。非同类型的对象之间不能进行转换,否则会抛出ClassCastException

    5. 语言对线程安全的支持。java从语言级支持线程。从而从语法和语言本身做了很多对线程的控制和支持。

    6. 垃圾回收。

    7. Exception。

    五、类加载

    1. 原理

    ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。

    当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。

    如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。

    JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。只有两者同时满足的情况下,JVM才认为这两个class是相同的。

    2. 加载器

    1. BootStrap ClassLoader

    启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等。

       URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
       for (int i = 0; i < urls.length; i++) {
           System.out.println(urls[i].toExternalForm());  
       }
       // 也可以通过sun.boot.class.path获取
       System.out.println(System.getProperty("sun.boot.class.path"))
    
    1. Extension ClassLoader

    扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar。

    1. App ClassLoader

    系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件

    注意

    除了Java默认提供的三个ClassLoader之外,用户还可以根据需要定义自已的ClassLoader,而这些自定义的ClassLoader都必须继承自java.lang.ClassLoader类,也包括Java提供的另外二个ClassLoader(Extension ClassLoader和App ClassLoader)在内。Bootstrap ClassLoader不继承自ClassLoader,因为它不是一个普通的Java类,底层由C++编写,已嵌入到了JVM内核当中,当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器。
    

    六、关键字

    strictfp(strict float point)

    strictfp 关键字可应用于类、接口或方法。使用strictfp关键字声明一个方法时,该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。当对一个类或接口使用strictfp关键字时,该类中的所有代码,包括嵌套类型中的初始设定值和代码,都将严格地进行计算。严格约束意味着所有表达式的结果都必须是 IEEE 754算法对操作数预期的结果,以单精度和双精度格式表示。

    如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp。

    transiant

    变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。

    volatile

    作为指令关键字,确保本条指令不会因编译器的优化而省略,修饰变量,保证变量每次都是从内存中重新读取。

    final

    1. 修饰基础数据成员(as const)

    2. 修饰类或对象的引用

    3. 修饰方法的final(cannot overwrite)

    4. 修饰类或者参数

    七、初始化

    父静态->子静态
    父变量->父初始化区->父构造
    子变量->子初始化区->子构造

    八、多线程

    JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

    1. 线程池

    concurrent下的线程池

    newSingleThreadExecutorExecutors

    创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

    1. newFixedThreadPool

    创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

    1. newCachedThreadPool

    创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

    1. newScheduledThreadPool

    创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

    2. 线程安全

    线程安全是一个很大的问题,Java 最常见的 HttpServlet 就是单实例多线程,解决这样的问题,有多种方式:

    1. ThreadLocal

      ThreadLocal 看下一节的内存图就很好理解,每个线程都有自己的工作内存,ThreadLocal 就是将变量存到线程自己的工作内存中,所以不会有并发问题。

    2. Synchronized
      synchronized锁住的是括号里的对象,而不是代码。对于非 static 的 synchronized 方法,锁的就是对象本身也就是 this。该关键字可以加到:

      • 实例方法

      • 静态方法

      • 实例方法中的同步块

      • 静态方法中的同步块

    3. ReentrantLock / Condition
      synchronized 不够灵活,例如读写文件,读和读之间不应该互斥,这个时候就可以使用 ReentrantLock 增加并发能力。Condition 是绑定到 Lock 上的,可以用于线程间通信,例如这个面试题,就可以使用 Condition 唤起线程写自己的name 。

      有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推…现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:A:1 2 3 4 1 2… B:2 3 4 1 2 3… C:3 4 1 2 3 4… D:4 1 2 3 4 1…

    4. 并发容器
      常见的 ConcurrentHashMap CopyOnWriteArrayList 用于多线程下存放数据,Queue BlockingQueue 用于排队消费。

    5. Atomic 包在 Atomic 包里一共有 12 个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段。某些并发问题,需要无锁解决时,就可以考虑使用原子方法。

    九、内存模型

    Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存,线程只能访问自己的工作内存,不可以访问其它线程的 工作内存。工作内存中保存了主内存共享变量的副本,线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步回到主内存当中。

    如何保证多个线程操作主内存的数据完整性是一个难题,Java内存模型也规定了工作内存与主内存之间交互的协议,首先是定义了8种原子操作:

    • lock:将主内存中的变量锁定,为一个线程所独占

    • unclock:将lock加的锁定解除,此时其它的线程可以有机会访问此变量

    • read:将主内存中的变量值读到工作内存当中

    • load:将read读取的值保存到工作内存中的变量副本中。

    • use:将值传递给线程的代码执行引擎

    • assign:将执行引擎处理返回的值重新赋值给变量副本

    • store:将变量副本的值存储到主内存中。

    • write:将store存储的值写入到主内存的共享变量当中。

    内存组成

    堆(Heap)

    运行时数据区域,所有类实例和数组的内存均从此处分配。Java虚拟机启动时创建。对象的堆内存由称为垃圾回收器 的自动内存管理系统回收。

    • News Generation(Young Generation即图中的Eden + From Space + To Space)

      • Eden 存放新生的对象

      • Survivor Space 两个 存放每次垃圾回收后存活的对象

    • Old Generation(Tenured Generation 即图中的Old Space) 主要存放应用程序中生命周期长的存活对象

    非堆内存

    JVM具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和方法数据,以及方法和构造方法的代码。它是在Java虚拟机启动时创建的。除了方法区外,Java虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。例如,JIT编译器需要内存来存储从Java虚拟机代码转换而来的本机代码,从而获得高性能。

    • Permanent Generation (图中的Permanent Space)存放JVM自己的反射对象,比如类对象和方法对象

    • native heap

    十、写到最后

    如果觉得本文对你有帮助的话,请你也不要吝啬你的赞,你们的支持是对我最大的鼓励。今天的Java知识分享就到这里!点关注,不迷路,关注程序员曾曾,每天分享不同的Java基础知识,想要知道更多Java基础知识的我这边整理了一个我自己的GitHub仓库:Java小白修炼手册,大家如果有需要可以自行查看

    展开全文
  • 写这篇文章的目的是想总结一下自己这么多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能...

    写这篇文章的目的是想总结一下自己这么多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能让大家更好学习和使用Java。

    这次介绍的主要内容是和J2SE相关的部分,另外,会在以后再介绍些J2EE相关的、和Java中各个框架相关的内容。

    经过这么多年的Java开发,以及结合平时面试Java开发者的一些经验,我觉得对于J2SE方面主要就是要掌握以下的一些内容。

    c9bf316ded1a

    1. JVM相关(包括了各个版本的特性)

    对于刚刚接触Java的人来说,JVM相关的知识不一定需要理解很深,对此里面的概念有一些简单的了解即可。不过对于一个有着3年以上Java经验的资深开发者来说,不会JVM几乎是不可接受的。

    JVM作为Java运行的基础,很难相信对于JVM一点都不了解的人可以把Java语言吃得很透。我在面试有超过3年Java经验的开发者的时候, JVM几乎就是一个必问的问题了。当然JVM不是唯一决定技术能力好坏的面试问题,但是可以佐证Java开发能力的高低。

    在JVM这个大类中,我认为需要掌握的知识有:

    JVM内存模型和结构

    GC原理,性能调优

    调优:Thread Dump, 分析内存结构

    class 二进制字节码结构, class loader 体系 , class加载过程 , 实例创建过程

    方法执行过程

    Java各个大版本更新提供的新特性(需要简单了解)

    2. Java的运行(基础必备)

    这条可能出看很简单,Java程序的运行谁不会呢?不过很多时候, 我们只是单纯通过IDE去执行Java程序,底层IDE又是如何执行Java程序呢?很多人并不了解。

    这个知识点是最最基本的Java开发者需要掌握的,初学Java,第一个肯定是教你如何在命令行中执行Java程序,但是很多人一旦把Java学完了,IDE用上了,就把这个都忘了。为什么强调要知道这个呢,知道了Java最纯粹的启动方式之后,你才能在启动出问题的时候,去分析当时启动的目录多少,执行命名如何,参数如何,是否有缺失等。 这样有利于你真正开发中去解决那些奇奇怪怪的可能和环境相关的问题。

    在这里需要掌握的知识有:

    Javac 编译Java文件为 class 文件

    Java 命令的使用, 带package的Java类如何在命令行中启动

    Java程序涉及到的各个路径(classpath, Java。library。path, Java运行的主目录等)

    3. 数据类型

    这条没有什么好多说的,无非就是Java中的基本类型和对象类型的掌握。可以再了解一些JDK如何自动转换方面的知识,包括装箱拆箱等,还要注意避免装箱之后的类型相等的判断

    主要知识点:

    基本类型: int, long, float, double, boolean , 。。。

    对应的对象类型: Integer 等类型到基本类型的转换, 装箱和拆箱

    Object类型: equals, hashcode

    String 类型的特点

    4. 对象和实例,对象的创建

    在这方面,开发者需要了解class和instance的概念以及之间的差别, 这是Java面向对象特性的一个基础。主要知识点有:

    Class和 Instance 的概念

    Instance 创建的过程:

    1、 无继承:分配内存空间, 初始化变量, 调用构造函数

    2、 有继承:处理静态动作, 分配内存空间, 变量定义为初始值 , 从基类->子类, 处理定义处的初始化, 执行构造方法

    需要注意的点:

    3、静态属性等从基类->子类进行初始化

    4、默认无参构造方法相关的特性

    5. 访问控制

    这也是Java封装特性的一个基础,需要掌握的有:

    public protected default private 对于class, method, field 的修饰作用

    c9bf316ded1a

    6. 流程控制

    Java 流程控制的基础, 虽然有些语法不一定很常用,但是都需要了解,并且在合适的地方使用它们。

    需要掌握的有:

    if, switch, loop, for, while 等流程控制的语法

    7. 面向对象编程的概念

    这是一个Java的核心概念,对于任何Java开发者都需要熟练掌握。Java中很多特性或者说知识点都是和Java面向对象编程概念相关的。在我的理解,一个好的开发者不仅仅需要了解这些特性(知识点)本身,也更需要知道这些对象在Java的面向对象编程概念中是如何体现出来的,这样更有利于开发者掌握Java这门开发语言,以及其他面向对象编程的语言。在这里只是简单罗列了一下,主要的知识点包括有:

    面向对象三大特性:封装,继承,多态; 各自的定义概念,有哪些特性体现出来,各自的使用场景

    静态多分派,动态单分派的概念

    重载的概念和使用

    继承:接口多实现,基类单继承

    抽象,抽象类,接口

    多态:方法覆盖的概念和使用

    接口回调

    8. Static

    静态属性在Java日常开发中也是经常使用,需要了解和 static 关键字相关的用法,还有和其他关键字的配合使用, 如是否可以和 abstract, final 等关键字联合使用。

    主要需要掌握的有:

    静态属性的定义,使用,以及类加载时如何初始化

    静态方法的定义和使用

    静态类的定义和使用

    静态代码块的定义和初始化时机

    9. 基础知识点

    这里主要罗列一些散落的,没有系统归类的一些Java知识点。在日常的开发中用到也不少。 这块内容其实还有很多,目前只是暂时归纳了这几个在这里:

    包括有:

    equals , hashcode , string/stringbuffer ,final , finally , finalize

    10.集合框架

    这个是一个需要多加掌握的部分,做Java开发,可以说没有不用到集合框架的,这很重要。但是这里的知识点并不难,但是对于集合最好要了解内部的实现方式,因为这样有助于你在各个不同的场景选择适合的框架来解决问题,比如有1W个元素的集合,经常要进行contains判断操作,知道了集合的特性或者内部实现,就很容易做出正确的选择。

    这里包括了如下内容(并发相关不包含在内):

    集合框架的体系: 基础Collection ,Map

    具体集合实现的内容, List ,Set ,Map 具体的实现,内部结构, 特殊的方法, 适用场景等

    集合相关的工具类 Collections 等的用法

    c9bf316ded1a

    11.异常框架

    异常在Java的开发中可能没有那么被重视。一般遇到异常,直接上抛,或者随便catch一下处理之后对于程序整体运行也没有什么大的影响。不过在企业级设计开发中, 异常的设计与处理的好坏,往往就关系着这个系统整体的健壮性。一个好的系统的异常对于开发者来说,处理应该统一,避免各处散落很多异常处理逻辑;对于系统来说,异常应该是可控的,并且是易于运维的,某些异常出现后,应该有应对的方法,知道如何运维处理,所以虽然异常框架很简单,但是对于整个企业级应用开发来说,异常处理是很重要的,处理好异常就需要了解Java中的异常体系。

    这部分需要掌握的知识点不多,主要就是:

    异常的体系:

    Throwable

    Exception

    RuntimeException

    Error

    RuntimeException 和 一般 Exception 的区别, 具体处理方法等

    12. Java IO

    IO 在Java中不仅仅是文件读写那么简单,也包括了 socket 网络的读写等等一切的输入输出操作。比如说 标准HTTP请求中Post的内容的读取也是一个输出的过程,等等…

    对于IO,Java不仅提供了基本Input、Output相关的api,也提供了一些简化操作的Reader、Writer等api,在某些开发(涉及大量IO操作的项目)中也很重要,一般日常的开发中也会涉及(日志,临时文件的读写等)。

    在这中的知识点主要有:

    基本IO的体系: 包括有InputStream , OutputStream, Reader/Writer, 文件读取,各种流读取等

    NIO 的概念, 具体使用方式和使用场景

    13.多线程并发

    多线程是Java中普遍认为比较难的一块。多线程用好了可以有效提高cpu使用率, 提升整体系统效率, 特别是在有大量IO操作阻塞的情况下;但是它也是一柄双刃剑, 如果用不好,系统非但提升不大,或者没有提升,而且还会带来多线程之间的调试时等问题。

    在多线程中内容有很多,只是简单说明一下Java中初步使用多线程需要掌握的知识点,以后有机会单独再详细介绍一些高级特性的使用场景。

    多线程的实现和启动

    callable 与 runable 区别

    syncrhoized ,reentrantLock 各自特点和比对

    线程池

    future 异步方式获取执行结果

    concurrent 包

    lock

    ..

    14.网络

    Java中也是提供了可以直接操作 TCP协议、UDP协议的API。在需要强调网络性能的情况下,可以直接使用TCP/UDP 进行通讯。在查看Tomcat等的源码中,就可以看到这些相关API的使用情况。不过一般也比较少会直接使用TCP,会使用诸如MINA、Netty这样的框架来进行处理,因为这个方面的开发涉及不多,所以就不再详细罗列了。

    15.时间日期处理

    几乎对于每个应用来说,时间日期的处理也是绕不过去的,但是JDK8 之前的时间相关API用法并不友好。在那个时代,可以选择Joda等时间框架。到了JDK8 发布之后,全新的时间API基本融合了其他框架的优点,已经可以很好的直接使用了。

    对于Java开发者来说,需要熟练地使用API来对时间和日期做相关的处理。

    具体知识点不再罗列,会在以后再写个专门的文章来总结一下JDK8中时间日期API的用法。

    c9bf316ded1a

    16.XML解析/ JSON解析

    其实这两块内容都不是J2SE里面的内容,但是在日常开发中,和其他程序交互,和配置文件交互,越来越离不开这两种格式的解析。

    不过对于一个开发者来说,能够了解一些XML/JSON具体解析的原理和方法,有助于你在各个具体的场景中更好的选择合适你的方式来使得你的程序更有效率和更加健壮。

    XML: 需要了解 DOM解析和 SAX解析的基本原理和各自的适用场景

    JSON: 需要了解一些常用JSON框架的用法, 如 Jackson, FastJson, Gson 等。。

    17.Maven的使用

    Maven也不是Java里面的内容,但是maven是革命性的,给Java开发带来了巨大的便利。从依赖的引入和管理,开发流程的更新和发布产出,乃至版本的更新,使用maven可以大大简化开发过程中的复杂度,从而节省大量时间。可以说,maven已经成为Java开发者的标配了。所以我把maven也作为一个Java开发者对于基础必备的知识点。以后会再放上一些我的一些对于maven使用的经验和技巧等,这里就不再细说了。

    18.泛型

    这是JDK5开始引入的新概念,其实是个语法糖,在编写Java代码时会有些许便利, 一般的应用或者是业务的开发,只需要简单使用,不一定会用到定义泛型这样的操作, 但是开发一些基础公共组件会使用到,可以在需要的时候再细看这个部分,一般情况下只要会简单使用即可。

    19.标注

    也是jdk5 之后引入的。spring是个优秀的框架,最开始就以xml作为标准的配置文件。不过到了Spring3 之后,尤其是 spring-boot 兴起之后,越来越推崇使用标注来简化xml配置文件了,对于开发者来说,可以节省不少xml配置的时间。但是劣势是在于标注散落在各个类中,不像xml,可以对所有配置有个全局性的理解和管理,所以还没有办法说完全就取代所有的xml。对于一般开发者,会使用标注即可,一些公共组建的开发者可能会需要了解标注的定义和实现,可以在具体需要的时候再细看。

    20.RMI

    RemoteMethodInvocation ,Java语言特有的远程调用接口,使用还是比较简单方便。不过需要跨语言的情况下,就需要使用 webservice 等其他方式来支持。一般来说,程序都不需要使用RMI,不过可以在特定的情况下使用,我就在一个项目中,使用RMI来进行程序远程启动停止的控制。

    21.JNI

    Java Native Interface,可以允许Java中调用本地接口方法,一般用于C/C++代码的调用。需要注意的是在Java中加载so/dll文件的路径问题,本身调用接口并不复杂,但是经常在是否加载了所需的本地接口库中花费较多时间。

    c9bf316ded1a

    以上也只是简单介绍了下我对于这些Java基本知识点和技术点的一些看法和介绍, 这些内容都源自于我这些年来使用Java的一些总结, 希望给刚刚接触Java, 或者打算从Java开发的人一些经验, 希望能够更有效率地学习和使用Java, 避免走了弯路浪费了宝贵的时间。这当中还有些内容不够完善的地方,会通过以后的文章再添加上。由于个人能力有限,当然其中也会有些错误和疏漏,欢迎指正,一起讨论,共同来把这篇文章再完善下,希望它可以真正帮助到有需要的人。

    ​​​​​

    展开全文
  • Java基础,Java语言,简单循环介绍

    软件开发

    软件:一系列按照特定顺序组织的计算机数据和指令的集合。

    常见的软件:

    系统软件:

    如:DOS,windows,Linux等。

    应用软件:

    如:扫雷,迅雷,QQ等。

    什么是开发?

    制作软件

    人机的交互方式 软件的出现实现了人与计算机之间的更好的交互

    交互方式:

    图形化界面:这种方式简单直观,使用者易于接受,容易上手操作

    命令行方式:需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记录一些命令。

    常用的DOS命令 dos命令行:

    dir:列出当前目录下的文件及文件夹

    md:创建目录

    rd:删除目录

    cd:进入指定目录

    cd..:退回上一级目录

    cd/:退回根目录

    del:删除文件

    exit:推出dos命令行

    计算机语言

    通过DOS命令行的演示,发现原来操作计算机就如同和计算机说话一样,我们告诉它做什么,它就可以做什么,前提是,我们和它说的内容它可以识别才可以,这就是计算机语言 Java语言概述 1:是SUN(Stanford University Networl,斯坦福大学网络公司)1995年推出的一门高级编程语言。

    2:是一种面向Internet的编程语言。

    3:随着Java技术在web方面的不断成熟,已经成为web应用程序的首选开发语言

    4:是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。

    Java语言的三种技术架构 1:J2EE(java 2 Platform Enterprise Edition)企业版

    是为开发企业环境下的应用程序提供的一套解决方案,该技术体系中包含的技术如Servlet,jsp等,主要针对于web应用程序开发

    2:J2SE(java 2 Platform Standard Edition)标准版

    是为开发普通桌面和商务应用提供的解决方案,该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发,比如看Java版的扫雷

    3:J2ME(java 2 Platform Micro Edition)小型版

    是为开发电子消费产品和嵌入设备提供的解决方案,该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。

    JAVA5.0版本后,更名为:JAVAEE JAVASE JAVAME

    Java语言的特点:跨平台性 什么是跨平台性?

    通过Java语言编写的应用程序在不同的系统平台上都可以运行

    原理是什么?

    只要在需要运行Java应用程序的操作系统上,先安装一个Java虚拟机(JVM Virtual Machine)即可,由JVM来负责Java程序在该系统中的运行

    Java语言的特点:跨平台性(图解):

    img

    因为有了JVM ,所以同一个Java程序在三个不同的操作系统中都可以执行,这样就实现了Java程序的跨平台性,也称为Java具有良好的移植性。

    Java语言的环境搭建 1:明确什么是JRE,JDK

    JRE(Java Runtime Enviroment java运行环境)

    包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

    JDK(Java Development Kit Java开发工具包)

    JDK是提供Java开发人员使用的,其中包含 了Java的开发工具,也包含了JRE。所以安装JDK,就不用再单独安装JRE了

    其中的开发工具:编译工具(javac.exe)打包工具(jar.exe)等

    简单而言:使用JDK开发完成的Java程序,交给JRE运行

    2:下载JDK

    JDK(Java Development Kit Java开发工具包)

    官方网址:

    www.oracle.com 参阅index.html

    Java.sun.com 参阅index.html

    3:安装JDK

    傻瓜式安装,下一步即可。

    建议:安装路径不要有中文或者特殊符号

    如空格等。

    当提示安装JRE时,可以选择不安装。

    4:配置环境变量

    配置环境变量path

    在dos命令行中敲入javac,出现错误提示。

    img

    错误原理:当前执行的程序在当前目录下如果不存在,windows系统

    会在系统中已有的一个名为path的环境变量指定的目录中查找。如果

    还没有找到,就出现以上的错误提示。

    所以进入到jdk安装路径\bin目录下,执行javac。看到javac参数提示信息。

    img

    每次执行java的工具都要进入到bin目录下,是非常麻烦的。可不可以在任何目录下都可以执行java的工具呢?

    根据windows系统在查找可执行程序的原理,可以将java工具所在路径定义到path环境变量中,让系统帮我们去找运行执行的程序。

    我的电脑--属性--高级--环境变量

    编辑path环境变量,在变量值开始处加上java工具所

    在目录,后面用 “ ; ”和其他值分隔开即可。

    临时配置方式:通过dos命令中set命令完成

    • set :用于查看本机的所有环境变量的信息。

    • set 变量名 :查看具体一个环境变量的值。

    • set 变量名=:清空一个环境变量的值。

    • set 变量名=具体值 :给指定变量定义具体值。

    想要在原有环境变量值基础上添加新值呢?

    • 首先,通过%变量名%操作符获取到原有环境变量的值。

    • 然后加上新值后在定义给该变量名即可

    • 举例:给path环境变量加入新值

    • set path=新值;%path%

    注意:这种配置方式只在当前dos窗口有效。窗口关闭,配置消失。

    5:验证是否成功

    打开DOS命令行,任意目录下敲入javac。 如果出现javac 的参数信息,配置成功。这种配置方式,一劳永逸

    6:配置技巧

    为了不因为jdk的目录或者目录名称的改变,而不断更改path的值,而导致对

    path变量值的误操作,可以通过以下技巧完成。

    • 新创建一个环境变量 JAVA_HOME 记录住jdk的目录。

    • 在path中通过%%动态的获取JAVA_HOME的值即可。

    • JAVA_HOME=F:\jdk1.6.0_01

    • path=%JAVA_HOME%\bin;%path%

    • %path%:动态获取path环境变量的值。

    • %JAVA_HOME%:动态获取名称为JAVA_HOME环境变量的值。

    Java语言基础组成

    关键字、

    关键字的定义和特点

    定义:被Java语言赋予了特殊含义的单词

    特点:关键字中所有字母都为小写

    用于定义数据类型的关键字

    class interface byte short int long float double char boolean void

    用于定义数据类型值得关键字

    true false null

    用于定义流程控制的关键字

    if else switch case default while do for break continue return

    用于定义访问权限修饰符的关键字

    private protected public

    用于定义类、函数、变量修饰符的关键字

    abstract final static synchronized

    用于定义类与类之间关系的关键字

    extends implements

    用于定义建立实例及引用实例,判断实例的关键字

    new this super instanceof

    用于异常处理的关键字

    try catch finally throw throws

    用于包的关键字

    package import

    其他修饰符关键字

    native strictfp transient volatile assert

    标识符、

    在程序中自定义的一些名称

    由26个英文字母大小写,数字:0-9符号:_$组成

    定义合法标识符规则:

    1:数字不可以开头

    2:不可以使用关键字

    Java中严格区分大小写

    注意:在起名字时,为了提高阅读性,要尽量有意义

    Java中的名称规范

    包名:多单词组成时所有字母都小写 如:xxxxyyyyzzz

    类名接口名:多单词组成时,所有单词的首字母大写 如:XxxxYyyyZzzz

    变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写 如:xxxYyyZzz

    常量名:所有字母都大写,多单词时每个单词用下划线连接 如:XXX_YYY_ZZZ

    注释、

    单行注释://

    多行注释:/**/

    常量和变量、

    变量的概念:

    内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型),该区域的数据可以咋同一个类型范围内不断变化

    为什么要定义变量:

    用来不断的存放同一类型的常量,并且可以重复使用

    使用变量注意:

    变量的作用范围(一对{}之间有效)

    初始化值

    定义变量的格式:

    数据类型 变量名 = 初始化值;

     

    注:格式是固定的,变量就如同数学中的未知数。

    Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存总分配了不同的大小的内存空间

    运算符、

    算术运算符

     

    算术运算符的注意问题

    如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。但被模数是负数就另当别论。对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。“+”除字符串相加功能外,还能把非字符串转换成字符串 ,

    赋值运算符

     

    符号:

    示例:

    int a,b,c; a=b=c=3;

    int a=3; a+=5;等同运算a=a+5

    比较运算符

     

    注意:比较运算符“==”不能误写成“=” ;

    逻辑运算符

     

    注意:逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。

    “&”和“&&”的区别:

    • 单&时,左边无论真假,右边都进行运算;

    • 双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。

    • “|”和“||”的区别同理,双或时,左边为真,右边不参与运算。

    • 异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。

    位运算符

     

    三元运算符

    格式:

    • (条件表达式)?表达式1:表达式2;

    • 如果条件为true,运算后的结果是表达式1;

    • 如果条件为false,运算后的结果是表达式2;

    示例:

    获取两个数中大数。

    int x=3,y=4,z;

    z = (x>y)?x:y;//z变量存储的就是两个数的大数。

    判断语句、循环

    if—else判断语句

    ######

      条件语句:
                1、正常的js语句都是从上到下逐行执行;
                2、条件语句,如果满足条件,继续执行,如果不满足条件,执行其他的代码
                    结构:
                      单分支: if(表达式1){
                                条件语句
                            }   
                        如果表达式1为true,执行if后面的代码块
    ​
                      双分支语句:
                            if(表达式1){
                                语句1;
                            }else{
                                语句2;
                            }
                            如果表达式为true,执行语句1,否则执行语句2
    ​
                被大括号包含的代码,被称为代码块
        */
        var source = 61;
        if(source<60){
            console.log("不及格");
            console.log("下次努力");
        }else{
            console.log("及格了");
        }

    条件分支语句:Switch

    /** 条件分支语句: switch(表达式){ case 表达式1: 语句1 break; case 表达式2: 语句2 break; ....... default: 语句n break; }

                1、适用条件,判断比较多,必须是全等(===)判断
                2、switch里面的变量会逐个和case后面的值做全等比较
                    如果相等会执行对应case后面的语句,下面case不再判断,语句会执行
                     break  中断代码块的执行
                3、default 如果case语句都没有执行,就会执行default后面的语句
        
        */
        /*
            输入数字,输出大写汉字
        
        */
        var a = 4;
        switch(a){
            case 1:
                console.log("壹");
                break;
            case 2:
                console.log("贰");
                break;
            case 3:
                console.log("叁");
                break;
            default:
                console.log("目前只支持1~3的转化");
                break;
        }

    for循环

    /** for循环

            1、循环变量的初始化(只执行一遍)
            2、循环变量判断,(符合条件执行循环体,否则不执行)
            3、循环体
            4、更新循环变量
    ​
        */
        //打印1~100的数字
        // for(var i=1;i<=100;i++){
        //     // 循环体
        //     console.log(i);
        // }
        //查看执行顺序
        // for(alert("初始化循环变量");confirm("循环变量判断");alert("更新循环变量")){
        //     alert("循环体");
        // }
    ​
         // 特殊for循环
        // var i=1
        // for(;i<=100;){
        //     console.log(i);
        //     i++;
        // }

    while循环语句

    /** 循环语句: 1、while 结构:while(表达式){ 循环体 } 1、当表达式为true的时候,执行循环体,直到表达式为false 如果表达式一直为true,就会成为死循环

                2、do{
                    循环体
                  }while(表达式)
                   先执行一遍循环体,在进行条件判断
    ​
                循环体的结构:
                    1、循环变量的初始化
                    2、循环变量判断,(符合条件执行循环体,否则不执行)
                    3、循环体
                    4、更新循环变量
        
        */
        //输出1到100的偶数的和
        // 分析:1、循环1到100的值
        //       2、循环的时候判断出偶数(2的倍数)
        //       3、求和
        var a = 1;
        var sum = 0;               
        while(a<=100){            
            if(a%2==0){
                // console.log(a);
                sum += a;  //sum = sum+a;
            }
            a++;
        }
        console.log(sum);
        //需要输出1到100的数
        // var a = 1;
        // while(a<=100){
        //     console.log(a);
        // }
    ​
        // console.log(a++);
        // console.log(a++);
        // console.log(a++);
        // console.log(1);
        // console.log(2);
        // console.log(3);
        // // .......
        // console.log(100);
    展开全文
  • 今天我写的这篇文章主要是总结一下从初学到现在的一些知识点,并且再帮自己复习一遍。 一、DOS命令 1、常见DOS命令 exit退出当前命令窗口 cls清屏 dir列出当前目录下所有的子文件/子目录 cd(改变目录) 假设...
  • Java基础知识总结(超详细整理)

    万次阅读 多人点赞 2021-07-17 10:00:08
    Java语言的特点,1.面向对象(OOP)就是Java语言的基础,也是Java语言的重要特性。面向对象的概念:生活中的一切事物都可以被称之为对象,生活中随处可见的事物就是一个对象,我们可以将这些事物的状态特征(属性)...
  • java知识点总结

    2021-03-06 00:20:19
    java知识点总结java都有哪些知识点?下面是小编整理总结的一些java知识点,希望对你有帮助。java知识点总结1. 基本数据类型整形:byte 1 个字节short 2 个字节int 4个字节long 8个字节字符:char 2个字节浮点数:...
  • Java期末复习知识点总结

    千次阅读 2021-06-13 12:35:03
    (1)包的概念 包是Java语言提供的一种区别类名的机制,是类的组织方法。在物理存储时,包就对应一个文件夹,包中还可以包含包,称为等级。同一个包中的类名不能重复,不同包中的类名可以相同,在引用某一个包的某...
  • 很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识。本文我总结了零基础学习Java编程的几个基础知识要点。希望能够对刚入门的Java新手有帮助。一、先了解什么是Java的四个方面初学...
  • 原标题:Java编程语言基础知识的要点很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识。下面就说说Java零基础学习Java编程语言基础知识的几个要点。希望能够对Java编程基础入门...
  • Java程序设计学习知识点总结Java语言简单,面向对象,分布式,解释性,健壮,安全与系统无关,可移植,高性能,多线程,动态语言。什么是框架可以认为是某种应用的半成品,就是一组组件用来完善自己的应用。简单地说...
  • 很多新手在学习java的时候都比较迷茫,不知道从哪里开始学起,这里就给大家整理了一份java开发学习路线,比较系统全面,可参考这份大纲来安排学习计划,希望可以帮到你~ ...知识点: 1、基本数据类型
  • 写这篇文章的目的是想总结一下自己这么多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能...
  • IP地址的这种表示法叫做"分十进制表示法",这显然比1和0容易记忆得多 IPv6:由于互联网的蓬勃发展,IP地址的需求量越来越大,但是网络地址资源有限,使得IP的分配越发紧张。 为了扩大地址空间,通过IPv6重新定义...
  • 原标题:给Java零基础新手学习java基础知识点讲解╰⊱⋛⋋殘祤菱幻⋌⋚⊰╯楼主刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,对于刚刚接触Java的新人人来说,J2SE方面主要就是要掌握以下的一些内容。...
  • 写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能...
  • Java学习—数组有关知识点总结 1.数组概念 数组概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。 **数组的定义方式:**1.数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度]; ...
  • Java知识点总结

    2021-04-12 08:16:16
    概念2.Java语言的主要特征2.1简单性Simple2.2 面向对象Object Oriented2.3分布式Distributed2.4健壮性Robust2.5安全性Secure2.6平台独立性/跨平台性Architecture neutral2.7可移植性Portable2.8解释型Interpreted2.9...
  • PC寄存器 PC寄存器保存的是当前正在执行...Java 语言消除了程序员回收无用内存空间的责任:JVM 提供了一种系统线程跟踪存储空间的分配情况。并在 JVM 的空闲时,检查并释放那些可以被释放的存储空间。垃圾回收器在 Java
  • java学习】java知识点总结java知识点总结1,java历史1.1 java基于C++1.1.1 JAVA和C++区别1.2 JDK(Java Development Kit)1.3 Java编码约定1.4 编译型语言、解释型语言、脚本语言任何语言都必须翻译成机器语言,...
  • Java泛型知识点总结

    2021-01-11 19:05:56
    Java泛型知识点总结 一、为什么要使用泛型 同一段代码,可以被很对不同类型的对象所重用,但我们并不希望为两个不同的对象设计不同的代码块。以ArrayList为例,AraryList可以存储任何类型的对象,JDK会为每一种类型...
  • 知识准备: JAVA应用程序的图形界面是通过JAVA API提供的java,awt,或 Java,swing包中的组件实现的。 GUI编程基础: 早期的JDK版本中提供了Java抽象窗口工具集,其目的是在程序 员创建图形界面时提供支持。但由于...
  • 写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能...
  • 原标题:Java知识点归纳Java学习不可不知的5个知识点学习Java知识要循序渐进,多练习,多实践,基础理论的学习不必可少。下面就是千锋广州老师总结出来的5大必学知识点,一起来看一下吧! 1.什么是线程线程是进程...
  • JAVA基础知识点总结

    2021-04-17 18:24:56
    本文主要是我之前复习Java基础原理过程中写的Java基础知识点总结Java知识点其实非常多,并且有些知识点比较难以理解,有时候我们自以为理解了某些内容,其实可能只是停留在表面上,没有理解其底层实现原理。 纸...
  • 原标题:【超详细】Java入门学习进阶知识点汇总 入门阶段,主要是培养Java语言的编程思想。了解Java语言的语法,书写规范等,掌握Eclipse、MyEclipse等开发工具,编写Java代码的能力。学完这个阶段你应该可进行小型...
  • Java相关知识点总结

    2021-03-11 14:24:53
    Java核心基础Java基础编程第一章_Java语言概述功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...
  • Java基础入门教程知识点汇总,学习Java技术开发需要我们制定合理的Java学习路线,这样我们学习起来才会更轻松。下面小编汇总了Java基础教程中的一些知识点。1、IDE:IDE(Integrated DevelopmentEnvironment,集成开发...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 133,204
精华内容 53,281
关键字:

java语言的知识点归纳

java 订阅