导图社区 javase
java基础学习资料整理、Java SE(Java Standard Edition,Java 标准版)是Java技术的核心和基础,是Java ME和Java EE编程的基础。Java SE是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的Hot Java浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览。
编辑于2023-03-19 13:43:36 河南学成在线-面试相关重点,具体有项目介绍、项目有关内容知识、git相关面试、Maven相关面试知识、MySQL相关面试、Springboot相关面试,喜欢的可以点赞收藏起来。
java基础资料、Java的第一道工序是通过javac命令把Java源码编译成字节码2、为了提高效率,JVM引入了 JIT 编译器,把一些经常执行的字节码直接搞成机器码。Java是解释和编译并存。
Java EE 是 J2EE的一个新的名称,之所以改名,目的还是让大家清楚J2EE只是Java企业应用。在2004年底中国软件技术大会Ioc微容器(也就是Jdon框架的实现原理)演讲中指出:我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件)。
社区模板帮助中心,点此进入>>
学成在线-面试相关重点,具体有项目介绍、项目有关内容知识、git相关面试、Maven相关面试知识、MySQL相关面试、Springboot相关面试,喜欢的可以点赞收藏起来。
java基础资料、Java的第一道工序是通过javac命令把Java源码编译成字节码2、为了提高效率,JVM引入了 JIT 编译器,把一些经常执行的字节码直接搞成机器码。Java是解释和编译并存。
Java EE 是 J2EE的一个新的名称,之所以改名,目的还是让大家清楚J2EE只是Java企业应用。在2004年底中国软件技术大会Ioc微容器(也就是Jdon框架的实现原理)演讲中指出:我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件)。
javase
打印Java数组
stream 流打印 Java 数组
Arrays.asList(cmowers).stream().forEach(s -> System.out.println(s))
for 循环打印 Java 数组
for(int i = 0; i < cmowers.length; i++){ System.out.println(cmowers[i]); } for (String s : cmowers) { System.out.println(s); }
Arrays 工具类打印 Java 数组Arrays工具类打印二维数组Arrays.deepToString() 方法。
String [] cmowers = {"沉默","王二","一枚有趣的程序员"}; System.out.println(Arrays.toString(cmowers));
String 类
第一,String 类是 final 的,意味着它不能被子类继承
第二,String 类实现了 Serializable 接口,意味着它可以序列化。
String 类实现了 Comparable 接口,意味着最好不要用‘==’来比较两个字符串是否相等,而应该用 compareTo() 方法去比较
第四,StringBuffer、StringBuilder 和 String 一样,都实现了 CharSequence 接口 由于 String 是不可变的,字符串拼接的时候使用String 的另外两个好兄弟,StringBuffer 和 StringBuilder,它俩是可变的
Java 9 以前,String 是用 char 型数组实现的,之后改成了 byte 型数组实现,并增加了 coder 来表示编码
第六,每一个字符串都会有一个 hash 值,这个哈希值在很大概率是不会重复的,因此 String 很适合来作为 HashMap 的键值
为什么String不可变
String 类被 final 关键字修饰,所以它不会有子类,这就意味着没有子类可以重写它的方法,改变它的行为
String 类的数据存储在 byte[] 数组中,而这个数组也被 final 关键字修饰了,这就表示 String 对象是没法被修改的,只要初始化一次,值就确定了。
String不可变的好处
第一,可以保证 String 对象的安全性,避免被篡改,毕竟像密码这种隐私信息一般就是用字符串存储的。 第二,保证哈希值不会频繁变更。毕竟要经常作为哈希表的键值,经常变更的话,哈希表的性能就会很差劲。 第三,可以实现字符串常量池。 “由于字符串的不可变性,String 类的一些方法实现最终都返回了新的字符串对象。”
String不管是截取、拼接,还是替换,都不是在原有的字符串上进行的,而是重新生成了新的字符串对象。也就是说,这些操作执行过后,原来的字符串对象并没有发生改变。”
记住,String 对象一旦被创建后就固定不变了,对 String 对象的任何修改都不会影响到原来的字符串对象,都会生成新的字符串对象。
字符串常量池
在Java中,栈上存储的是基本数据类型的变量和对象的引用,而对象本身则存储在堆上。
String s = new String("二哥");,它创建了两个对象:一个是字符串对象 "二哥",它被添加到了字符串常量池中,另一个是通过 new String() 构造函数创建的字符串对象 "二哥",它被分配在堆内存中,同时引用变量 s 存储在栈上,它指向堆内存中的字符串对象 "二哥
由于字符串的使用频率实在是太高了,所以 Java 虚拟机为了提高性能和减少内存开销,在创建字符串对象的时候进行了一些优化,特意为字符串开辟了一块空间——也就是字符串常量池。
字符串常量池的作用
我们会采用双引号的方式来创建字符串对象 String s = "三妹"; Java 虚拟机会先在字符串常量池中查找有没有“三妹”这个字符串对象,如果有,则不创建任何对象,直接将字符串常量池中这个“三妹”的对象地址返回,赋给变量 s;如果没有,在字符串常量池中创建“三妹”这个对象,然后将其地址返回,赋给变量 s。
字符串常量池在内存中的什么位置呢?
Java 7 字符串常量池位于永久代(Permanent Generation)的内存区域中,主要用来存储一些字符串常量(静态数据的一种)。永久代是 Java 堆(Java Heap)的一部分,用于存储类信息、方法信息、常量池信息等静态数据。 到了 Java 8,永久代(PermGen)被取消,并由元空间(Metaspace)取代
Java 基本数据类型缓存池
基本数据类型的包装类除了 Float 和 Double 之外,其他六个包装器类(Byte、Short、Integer、Long、Character、Boolean)都有常量缓存池
Byte:-128~127,也就是所有的 byte 值 Short:-128~127 Long:-128~127 Character:\u0000 - \u007F Boolean:true 和 false
拿 Integer 来举例子,Integer 类内部中内置了 256 个 Integer 类型的缓存数据,当使用的数据范围在 -128~127 之间时,会直接返回常量池中数据的引用,而不是创建对象,超过这个范围时会创建新的对象。
在 Java 中,针对一些基本数据类型(如 Integer、Long、Boolean 等),Java 会在程序启动时创建一些常用的对象并缓存在内存中,以提高程序的性能和节省内存开销。
String、StringBuilder、StringBuffer 三兄弟
String字符串
由于字符串是不可变的,所以当遇到字符串拼接(尤其是使用+号操作符)的时候,就需要考量性能的问题,你不能毫无顾虑地生产太多 String 对象,对珍贵的内存造成不必要的压力。
StringBuffer
由于 StringBuffer 操作字符串的方法加了 synchronized 关键字进行了同步,主要是考虑到多线程环境下的安全问题,所以执行效率会比较低
StringBuilder
在单线程环境下使用,这样效率会高得多,如果要在多线程环境下修改字符串,你到时候可以使用 ThreadLocal 来避免多线程冲突
StringBuffer和StringBuiler除了类名不同,方法没有加 synchronized,基本上完全一样。 实际开发中,StringBuilder 的使用频率也是远高于 StringBuffer,甚至可以这么说,StringBuilder 完全取代了 StringBuffer。
Java 编译器将字符串拼接操作(+)转换为了 StringBuilder 对象的 append 方法,然后再调用 StringBuilder 对象的 toString 方法返回拼接后的字符串
java如何判断两个字符串是否相等? .equals() 和 ‘==’ 操作符有什么区别?
“==”操作符用于比较两个对象的地址是否相等
.equals() 方法用于比较两个对象的内容是否相等
Object 类的 .equals() 方法默认采用的是“==”操作符进行比较。假如子类没有重写该方法的话,那么“==”操作符和 .equals() 方法的功效就完全一样——比较两个对象的内存地址是否相等。
除了 .equals() 方法,还有其他两个可选的方案。” 1、Objects.equals() 这个静态方法的优势在于不需要在调用之前判空。 2)String 类的 .contentEquals() .contentEquals() 的优势在于可以将字符串与任何的字符序列(StringBuffer、StringBuilder、String、CharSequence)进行比较
Java字符串拼接是哪种方式?
循环体内,拼接字符串最好使用 StringBuilder 的 append() 方法,而不是 + 号操作符
原来编译的时候把“+”号操作符替换成了 StringBuilder 的 append() 方法 原因就在于循环体内如果用 + 号操作符的话,就会产生大量的 StringBuilder 对象,不仅占用了更多的内存空间,还会让 Java 虚拟机不停的进行垃圾回收,从而降低了程序的性能
1)判断拼接的字符串是不是 null,如果是,当做字符串“null”来处理。appendNull() 2)获取字符串的长度。 3)ensureCapacityInternal() 方法:由于字符串内部是用数组实现的,所以需要先判断拼接后的字符数组长度是否超过当前数组的长度,如果超过,先对数组进行扩容,然后把原有的值复制到新的数组中 4)将拼接的字符串 str 复制到目标数组 value 中。 5)更新数组的长度 count。
其他的字符串拼接方法
String 类的 concat() 方法,有点像 StringBuilder 类的 append() 方法
String 类有一个静态方法 join()
String cmower = String.join("", chenmo, wanger);
StringUtils.join 拼接字符串
StringUtils.join(chenmo, wanger);
java中的抽象类abstract
1、抽象类不能被实例化。
2、抽象类应该至少有一个抽象方法,否则它没有任何意义。
3、抽象类中的抽象方法没有方法体。
4、抽象类的子类必须给出父类中的抽象方法的具体实现,除非该子类也是抽象类。
java中的接口 inerface
接口通过 interface 关键字来定义,它可以包含一些常量和方法
接口中定义的所有变量或者方法,都会自动添加上 public 关键字 接口中定义的变量会在编译的时候自动加上 public static final 修饰符
5)接口的变量是隐式 public static final(常量),所以其值无法改变
接口中允许定义变量 接口中允许定义抽象方法 接口中允许定义静态方法(Java 8 之后) 接口中允许定义默认方法(Java 8 之后)
1)接口不允许直接实例化,否则编译器会报错。 需要定义一个类去实现接口,然后再实例化。
2)接口可以是空的,既可以不定义变量,也可以不定义方法。最典型的例子就是 Serializable 接口
3)不要在定义接口的时候使用 final 关键字,否则会报编译错误,因为接口就是为了让子类实现的,而 final 阻止了这种行为。
4)接口的抽象方法不能是 private、protected 或者 final,否则编译器都会报错。
接口的作用?
第一,使某些实现类具有我们想要的功能。比如说,实现了 Cloneable 接口的类具有拷贝的功能
第二,Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的
第三,实现多态。多态可以通过继承extends的关系实现,也可以通过接口的形式实现。
说一下多态存在的 3 个前提: 1、要有继承关系,比如说 Circle 和 Square 都实现了 Shape 接口。 2、子类要重写父类的方法,Circle 和 Square 都重写了 name() 方法。 3、父类引用指向子类对象,circleShape 和 squareShape 的类型都为
java 抽象类和接口的区别
在 Java 中,通过关键字 abstract 定义的类叫做抽象类。 接口(英文:Interface),在 Java 中是一个抽象类型,是抽象方法的集合;接口通过关键字 interface 来定义
接口与抽象类的不同之处在于: 1、抽象类可以有方法体的方法,但接口没有(Java 8 以前)。 2、接口中的成员变量隐式为 static final,但抽象类不是的。 3、一个类可以实现多个接口,但只能继承一个抽象类。
设计层面上 抽象类是对一种事物的抽象,即对类抽象,继承抽象类的子类和抽象类本身是一种 is-a 的关系。而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
1)语法层面上 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法; 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的; 接口中不能含有静态代码块,而抽象类可以有静态代码块; 一个类只能继承一个抽象类,而一个类却可以实现多个接口
java中的内部类
成员内部类(类内部的class类)
内部类 Wangxiaoer 就好像 Wanger 的一个成员,成员内部类可以无限制访问外部类的所有成员属性 但外部类想要访问内部类的成员,就不那么容易了,必须先创建一个成员内部类的对象,再通过这个对象来访问:
局部内部类(定义在一个方法或者一个作用域里面的类)
局部内部类是定义在一个方法或者一个作用域里面的类,所以局部内部类的生命周期仅限于作用域内。
局部内部类就好像一个局部变量一样,它是不能被权限修饰符修饰的,比如说 public、protected、private 和 static 等。
匿名内部类
匿名内部类是唯一一种没有构造方法的类。就上面的写法来说,匿名内部类也不允许我们为其编写构造方法,因为它就像是直接通过 new 关键字创建出来的一个对象。 匿名内部类的作用主要是用来继承其他类或者实现接口,并不需要增加额外的方法,方便对继承的方法进行实现或者重写
静态内部类
静态内部类和成员内部类类似,只是多了一个 static 关键字。
由于 static 关键字的存在,静态内部类是不允许访问外部类中非 static 的变量和方法的,这一点也非常好理解:你一个静态的内部类访问我非静态的成员变量干嘛?
为什么要使用内部类呢?
1、内部类可以使用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。 2、在单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。 3、创建内部类对象的时刻并不依赖于外部类对象的创建。 4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。 5、内部类提供了更好的封装,除了该外围类,其他类都不能访问
java面向对象的三大特征
封装
封装从字面上来理解就是包装的意思,是指利用抽象将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。
使用封装有 4 大好处: 1、良好的封装能够减少耦合。 2、类内部的结构可以自由修改。 3、可以对成员进行更精确的控制。 4、隐藏信息,实现细节。
数据被保护在类的内部,尽可能地隐藏内部的实现细节,只保留一些对外接口使之与外部发生联系。 其他对象只能通过已经授权的操作来与这个封装的对象进行交互。也就是说用户是无需知道对象内部的细节(当然也无从知道),但可以通过该对象对外的提供的接口来访问该对象。
继承:extends
在 Java 语言中继承就是子类继承父类的属性和方法,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的方法。
Java 语言只支持类的单继承,但可以通过实现接口的方式达到多继承的目的。
Java 虽然不支持多继承,但是 Java 有三种实现多继承效果的方式,分别是内部类、多层继承和实现接口。
多态
Java 多态是指在面向对象编程中,同一个类的对象在不同情况下表现出不同的行为和状态。
1)子类可以继承父类的属性和方法,子类对象可以直接使用父类中的方法和变量。 2)子类可以对从父类继承的方法进行重新实现,使得子类对象调用这个方法时表现出不同的行为。 3)可以将子类对象赋给父类类型的变量,这样就可以通过父类类型的变量调用子类中重写的方法,实现多态。
多态的前提条件有三个: 子类继承父类 子类覆盖父类的方法 父类引用指向子类对象
java中的关键字
.this关键字
this 关键字有很多种用法 调用当前类的方法; this() 可以调用当前类的构造方法; this 可以作为参数在方法中传递; this 可以作为参数在构造方法中传递; this 可以作为方法的返回值,返回当前类的对象。
.super关键字
“super 关键字的用法主要有三种。” 指向父类对象; 调用父类的方法; super() 可以调用父类的构造方法。
“如果父类和子类拥有同样名称的字段,super 关键字可以用来访问父类的同名字段。”
“当子类和父类的方法名相同时,可以使用 super 关键字来调用父类的方法。换句话说,super 关键字可以用于方法重写时访问到父类的方法。”
在默认情况下,super() 是可以省略的,编译器会主动去调用父类的构造方法 子类即使不使用 super() 主动调用父类的构造方法,父类的构造方法仍然会先执行。
“super() 也可以用来调用父类的有参构造方法,这样可以提高代码的可重用性。”
static关键字
static 关键字的作用可以用一句话来描述:‘方便在没有创建对象的情况下进行调用,包括变量和方法’。也就是说,只要类被加载了,就可以通过类名进行访问。
静态变量 “如果在声明变量的时候使用了 static 关键字,那么这个变量就被称为静态变量。静态变量只在类加载的时候获取一次内存空间,这使得静态变量很节省内存空间
静态方法
“静态方法有以下这些特征。” 静态方法属于这个类而不是这个类的对象; 调用静态方法的时候不需要创建这个类的对象; 静态方法可以访问静态变量。
先是在静态方法中访问非静态变量,编译器不允许。”
然后在静态方法中访问非静态方法,编译器同样不允许。”
为什么 main 方法是静态的啊? 如果 main 方法不是静态的,就意味着 Java 虚拟机在执行的时候需要先创建一个对象才能调用 main 方法,而 main 方法作为程序的入口,创建一个额外的对象显得非常多余。
静态代码块 用一个 static 关键字,外加一个大括号括起来的代码被称为静态代码块。
静态代码块通常用来初始化一些静态变量,它会优先于 main() 方法执行
静态代码块在初始集合的时候,真的非常有用。在实际的项目开发中,通常使用静态代码块来加载配置文件到内存当中。
静态内部类
Java 允许我们在一个类中声明一个内部类,它提供了一种令人信服的方式,允许我们只在一个地方使用一些变量,使代码更具有条理性和可读性。
第一,静态内部类不能访问外部类的所有成员变量; 第二,静态内部类可以访问外部类的所有静态变量,包括私有静态变量。 第三,外部类不能声明为 static。
final关键字
final 变量
被 final 修饰的变量无法重新赋值。换句话说,final 变量一旦初始化,就无法更改
final 修饰的成员变量必须有一个默认值,否则编译器将会提醒没有初始化
final 和 static 一起修饰的成员变量叫做常量,常量名必须全部大写。
用 final 关键字来修饰参数,它意味着参数在方法体内不能被再修改。
final 方法
被 final 修饰的方法不能被重写。如果我们在设计一个类的时候,认为某些方法不应该被重写,就应该把它设计成 final 的
一个类是 final 的,和一个类不是 final,但它所有的方法都是 final 的,考虑一下,它们之间有什么区别?
我能想到的一点,就是前者不能被继承,也就是说方法无法被重写;后者呢,可以被继承,然后追加一些非 final 的方法。
final 类
如果一个类使用了 final 关键字修饰,那么它就无法被继承.....
为什么 String 类要设计成 final 吗? 原因大致有 3 个。” 为了实现字符串常量池 为了线程安全 为了 HashCode 的不可变性
instanceof关键字