java基础
语法
static 除了修饰属性和⽅法外,还有静态代码块 的功能,可⽤于类的初始化操作。进⽽提升程序的性能。(问:为什么提高性能?)
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。
Java中是否可以覆盖(override)一个private或者是static的方法?
Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n391" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class StaicBlock {
static{
System.out.println("I'm A static code block");
}
}</pre>
final 修饰类时,表明这个类不能被继承。final 类中的成员变量可以根据需要设为 final,但是要注意 final 类中的所有成员⽅法都会被隐式地指定为 final ⽅法。 final 修饰⽅法时,表明这个⽅法不能被任何⼦类重写,因此,如果只有在想明确禁⽌该⽅法在⼦类中被覆盖的情况下才将⽅法设置为 final。 final 修饰变量分为两种情况,⼀种是修饰基本数据类型,表示数据类型的值不能被修改;⼀种是修饰引⽤类型,表示对其初始化之后便不能再让其指向另⼀个对象。
接口
interface 接⼝是⼀个完全抽象的类,他不会提供任何⽅法的实现,只是会进⾏⽅法的定义。 接⼝中只能使⽤两种访问修饰符,⼀种是 public ,它对整个项⽬可⻅;⼀种是 default 缺省值,它只具有包访问权限。 接⼝只提供⽅法的定义,接⼝没有实现,但是接⼝可以被其他类实现。也就是说,实现接⼝的类需要提供⽅法的实现,实现接⼝使⽤ implements 关键字来表示,⼀个接⼝可以有多个实现。
接⼝不能被实例化,所以接⼝中不能有任何构造⽅法,你定义构造⽅法编译会出错。
可以在接口中定义默认方法。子类不需要实现所有方法,可以按需实现,或者直接使用接口的默认方法
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n645" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
public interface Animal {
//所有动物都需要吃东西,具体吃什么,让子类去实现
void eat();
default void run(){
System.out.println("我跑");
}
}
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("小猫爱吃鱼!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.run();
}
}
</pre>
在 JDK8 的集合中,就对 Collection 接口进行了拓展,如增加默认方法 stream() 等。既增强了集合的一些功能,而且也能向下兼容,不会对集合现有的继承体系产生影响。
接口中也可以定义静态方法。这样,就可以直接通过接口名调用静态方法。(这也很正常,接口本来就不能实例化)
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n637" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
public interface MyStaticInterface {
static void method(){
System.out.println("这是接口的静态方法");
}
</pre>
需要注意的是,不能通过实现类的对象去调用接口的静态方法。接⼝的实现⽐如实现接⼝的全部⽅法,否则必须定义为抽象类,这就是我们下⾯要说的内容
抽象 抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。Java支持创建只暴露接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。
抽象和封装的不同点 抽象和封装是互补的概念。一方面,抽象关注对象的行为。另一方面,封装关注对象行为的细节。一般是通过隐藏对象内部状态信息做到封装,因此,封装可以看成是用来提供抽象的一种策略。(??)
如果⼀个类中有抽象⽅法,那么这个类⼀定是抽象类,也就是说,使⽤关键字 abstract 修饰的⽅法⼀定是抽象⽅法,具有抽象⽅法的类⼀定是抽象类。实现类⽅法中只有⽅法具体的实现。
abstract void SmallBody();
抽象类中不⼀定只有抽象⽅法,抽象类中也可以有具体的⽅法,你可以⾃⼰去选择是否实现这些⽅法。 抽象类中的约束不像接⼝那么严格,你可以在抽象类中定义 构造⽅法、抽象⽅法、普通属性、⽅法、静态属性和静态⽅法 抽象类和接⼝⼀样不能被实例化,实例化只能实例化具体的类
[图片上传失败...(image-44bffa-1625478648052)]
枚举:
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n531" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public enum example{
AB,
BC,
CD
}
example aexample = example.AB;
System.out.println(aexample);//输出AB
System.out.println(aexample.ordinal());//输出0 枚举的声明顺序
for(example ae:example.values())
System.out.println(ae);//输出 AB BC CD
System.out.println(example.values());//输出ch1.UdpServer$example;@4554617c</pre>
枚举和普通类⼀样 枚举就和普通类⼀样,除了枚举中能够⽅便快捷的定义常量,我们⽇常开发使⽤的 public static final xxx 其实都可以⽤枚举来定义。在枚举中也能够定义属性和⽅法,千万不要把它看作是异类,它和万千的类⼀样。
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n541" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public enum OrdinalEnum {
WEST("live in west"),
EAST("live in east"),
SOUTH("live in south"),
NORTH("live in north");
String description;
OrdinalEnum(String description){
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static void main(String[] args) {
for(OrdinalEnum ordinalEnum : OrdinalEnum.values()){
System.out.println(ordinalEnum.getDescription());
}
}
}</pre>
⼀般 switch 可以和 enum ⼀起连⽤,来构造⼀个⼩型的状态转换机
枚举神秘之处
在 Java 中,万事万物都是对象,enum 虽然是个关键字,但是它却隐式的继承于 Enum 类。我们来看⼀下 Enum 类,此类位于 java.lang 包下,可以⾃动引⽤。
[图片上传失败...(image-73715b-1625478648052)]
注解
Java 注解(Annotation) ⼜称为元数据 ,它为我们在代码中添加信息提供了⼀种形式化的⽅法。它是 JDK1.5 引⼊的,Java 定义了⼀套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在java.lang.annotation 中。
作⽤在代码中的注解有三个,它们分别是
@Override : 重写标记,⼀般⽤在⼦类继承⽗类后,标注在重写过后的⼦类⽅法上。如果发现 其⽗类,或者是引⽤的接⼝中并没有该⽅法时,会报编译错误。 @Deprecated :⽤此注解注释的代码已经过时,不再推荐使⽤ @SuppressWarnings : 这个注解起到忽略编译器的警告作⽤
元注解有四个,元注解就是⽤来标志注解的注解。它们分别是 @Retention : 标识如何存储,是只在代码中,还是编⼊class⽂件中,或者是在运⾏时可以通过反射访问。 RetentionPolicy.SOURCE:注解只保留在源⽂件,当 Java ⽂件编译成class⽂件的时候,注解被遗弃; RetentionPolicy.CLASS:注解被保留到 class ⽂件,但 jvm 加载 class ⽂件时候被遗弃,这是默认的 ⽣命周期; RetentionPolicy.RUNTIME:注解不仅被保存到 class ⽂件中,jvm 加载 class ⽂件之后,仍然存在;
@Documented : 标记这些注解是否包含在 JavaDoc 中。
@Target : 标记这个注解说明了 Annotation 所修饰的对象范围,Annotation 可被⽤于packages、types(类、接⼝、枚举、Annotation类型)、类型成员(⽅法、构造⽅法、成员变量、枚举值)、⽅法参数和本地变量(如循环变量、catch参数)。取值如下
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="java" cid="n598" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}</pre>
@Inherited : 标记这个注解是继承于哪个注解类的。
从 JDK1.7 开始,⼜添加了三个额外的注解,它们分别是
@SafeVarargs :在声明可变参数的构造函数或⽅法时,Java 编译器会报 unchecked 警告。使⽤ @SafeVarargs 可以忽略这些警告 @FunctionalInterface : 表明这个⽅法是⼀个函数式接⼝ @Repeatable : 标识某注解可以在同⼀个声明上使⽤多次。
只要类上边看到了 @FunctionalInterface
这个注解,你都可以使用 lambda 表达式来简化写法。
lambda:
lambda 表达式语法如下:
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n616" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">(参数1,参数2) -> { 方法体 }</pre>
//遍历数组里边的元素,并打印,用lambda表达式
String[] arr = new String[]{"zhangsan","lisi"};
Arrays.asList(arr).forEach((s)-> System.out.println(s));
方法引用有以下四种形式:
对象 :: 实例方法
类 :: 静态方法
类 :: 实例方法
类 :: new
关于null
[图片上传失败...(image-695cf4-1625478648051)]
组合与继承
[图片上传失败...(image-af5041-1625478648051)]
[图片上传失败...(image-b190a7-1625478648051)]
Java内存
堆:存放所有new的对象和数组,可以被所有线程共享,不会存放别的对象的引用
栈:存放基本变量类型(包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:可以被所有的线程共享,包含了所有class和static变量