Java预习

sdjasj

一、零碎知识点

  • Java中字符串"=="判断两个字符串地址是否相等,.equals()判断字符串是否相等
  • final关键字只是表示对象引用不会再指向另一个不同的对象,但当前的对象可以更改
  • 静态方法是不在对象上执行的方法
  • 数组作为参数是引用传递,可以在方法中修改传递过来的数组
  • main 方法是被 JVM 调用的
  • 方法重载:一个类的两个方法拥有相同的名字,但是有不同的参数列表(重载的方法必须拥有不同的参数列表。你不能仅仅依据修饰符或者返回类型的不同来重载方法。)
  • 不管你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,它把所有成员初始化为0
  • JVM常量池保证相同的字符串直接量只有一个,不会产生多个副本,s1 = “ab”, s2 = “a” + “b”,s2直接引用常量池中的"ab",s1与s2指向同一个对象
  • Objects类的克隆是浅克隆,对象实例变量只复制了引用

img

二、方法修饰符

  1. public(公共控制符),包外包内都可以调用该方法。
  2. protected(保护访问控制符)指定该方法可以被它的类和子类进行访问。具体细节可参考:http://blog.csdn.net/dawn_after_dark/article/details/74453915
  3. default(默认权限),指定该方法只对同包可见,对不同包(含不同包的子类)不可见。
  4. private(私有控制符)指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类),非常严格的控制。
  5. final,指定方法已完备,不能再进行继承扩充。
  6. static,指定不需要实例化就可以激活的一个方法,即在内存中只有一份,通过类名即可调用。
  7. synchronize,同步修饰符,在多个线程中,该修饰符用于在运行前,对它所属的方法加锁,以防止其他线程的访问,运行结束后解锁。
  8. native,本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。
  9. abstract,抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。抽象方法不能被声明成 final 和 static。任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。 抽象方法的声明以分号结尾,例如:public abstract sample();

三、变量修饰符

1、成员变量修饰符

  1. public(公共访问控制符),指定该变量为公共的,它可以被任何对象的方法访问。
  2. protected(保护访问控制符)指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。
  3. default(默认权限),指定该变量只对同包可见,对不同包(含不同包的子类)不可见。
  4. private(私有访问控制符)指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。
  5. final,最终修饰符,指定此变量的值不能变。
  6. static(静态修饰符)指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。
  7. transient(过度修饰符)指定该变量是系统保留,暂无特别作用的临时性变量。不持久化。
  8. volatile(易失修饰符)指定该变量可以同时被几个线程控制和修改,保证两个不同的线程总是看到某个成员变量的同一个值。

final 和 static 经常一起使用来创建常量。

2、局部变量修饰符

只能使用 final 修饰局部变量
(1)为什么不能赋予权限修饰符?
因为局部变量的生命周期为一个方法的调用期间,所以没必要为其设置权限访问字段,既然你都能访问到这个方法,所以就没必要再为其方法内变量赋予访问权限,因为该变量在方法调用期间已经被加载进了虚拟机栈,换句话说就是肯定能被当前线程访问到,所以设置没意义。
(2)为什么不能用static修饰
我们都知道静态变量在方法之前先加载的,所以如果在方法内设置静态变量,可想而知,方法都没加载,你能加载成功方法内的静态变量?

java一个包可以有无数个public类,但一个文件只能有一个public类
继承链中对象方法的调用的优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。(父类引用指向子类对象)

五、多态

  • 编译时结果和运行时结果不一样(父类引用指向子类对象,只能使用父类中的方法(被子类重写的调用子类))
  • 向上转型与向下转型

六、java中遍历集合的三种方式

集合遍历操作的三种方式

  1. Iterator迭代器方式
  2. 增强for循环
  3. 普通for循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void test3(){
ArrayList list = new ArrayList();
list.add(123);
list.add("AAAA");
list.add("bb");
list.add(new String("JavaEE"));
list.add(new Date());
list.add(false);
// 遍历
//1.Iterator迭代器方式
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}

//2.增强for循环
for(Object obj:list){
System.out.println(obj);
}
//3.普通for循环
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}

七、内部类

  • 与内部类相对的外部类只有public和默认访问权限,前者可以被任何位置访问,后者只能被同一个包内的其他类访问。而内部类因为在外部类中,所以有public private protected等修饰

1.非静态内部类

1
2
3
4
5
6
7
8
9
10
public class A{
//非静态内部类
class B{
....
}
....
}
//实例化内部类
A a = new A();
A.B b = a.new B();
  • 内部类编译后的格式是Outerclass$InnerClass.class

  • 非静态内部类可以访问外部类的private成员(内部类对象中有隐式引用指向外部类对象),但外部类不能直接访问内部类的任何成员,只能通过创建内部类对象来访问其实例成员

  • 在非静态内部类中,外部类成员变量与非静态内部类成员变量和局部变量重名时(如都为lbh),访问局部变量直接使用lbh,非静态内部类成员变量使用this.lbh,外部类使用A.this.lbh(A为外部类名称)

  • 根据静态成员不能访问非静态成员的规则,外部类的静态成员(静态初始化块、静态方法)不能直接使用非静态内部类。同时非静态内部类里不能定义静态方法、成员等

  • 非静态内部类的子类可以是外部类,但也有对外部类对象的隐式引用

2.静态内部类

1
2
3
4
5
6
7
public class A{
//静态内部类
static class B{
....
}
....
}
  • 静态内部类可以包含静态和非静态的成员,根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。外部类不能直接访问静态内部类的成员,但可以通过B.name访问静态内部类的类成员,通过静态内部类的对象访问实例成员

3.内部类使用

  • 在外部类内部使用

​ 和普通实例化一样

  • 在外部类外部使用

(1)非静态内部类

OuterClass.InnerClass varname = new OuterClass.new InnerClass(); 非静态内部类的构造器必须由外部类来调用

(2)静态内部类

OuterClass.InnerClass varname = new OuterClass.InnerClass();

4.局部内部类

  • 方法中定义,与普通类使用一样

5.匿名内部类

  • 使用局部内部类时,只想创建这个类的一个对象时使用匿名内部类

  • 从上面定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则。1、匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因
此不允许将匿名内部类定义成抽象类。2、
匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类
可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事情。

  • 匿名内部类语法
1
2
3
4
new SuperType(construction parameters){
inner class methods and data
}
//可以实现接口(Comparator)和扩展超类
  • 双括号初始化
1
2
3
4
5
6
7
8
9
10
11
12
List<Integer> list = new LinkedList<>(){
{
add(1);
add(2);
}
};
Map<String, Integer> map = new HashMap<>(){
{
put("a",114514);
put("lbh",66666);
}
};

注意:(以map为例)双括号初始化其实是利用匿名内部类实例化了一个HashMap的子类,子类中有初始化块,并向上转型为HashMap,引用传给map

八、类与对象

  • 如果需要在子类方法中调用父类被覆盖的实例方法,则可使用 super 限定来调用父类被覆盖的实例方法。

  • 构造器不能用void声明,因为这是Java语法规定。实际上构造器返回的是类的对象。

构造器

  • 如果程序员没有为 Java 类提供任何构造器,则系统会为这个类提供一个无参数的构造器,这个构造器的执行体为空,不做任何事情。无论如何,Java类至少包含一个构造器。
  • 当构造器B完全包含构造器A时,可以在构造器B中使用this(a,b,c)调用A构造器简化程序

子类调用父类构造器

不管是否使用super 调用来执行父类构造器的初始化代码,子类构造器总会调用父类构造器一次。子类构造器调用父类构造器分如下几种情况。

* 子类构造器执行体的第一行使用 super 显式调用父类构造器,系统将根据 super调用里传入的实
参列表调用父类对应的构造器。

  • 子类构造器执行体的第一行代码使用 this 显式调用本类中重载的构造器,系统将根据 this 调用里
传入的实参列表调用本类中的另一个构造器。执行本类中另一个构造器时即会调用父类构造器。>

  • 子类构造器执行体中既没有 super 调用,也没有 this 调用,系统将会在执行子类构造器之前,隐
式调用父类无参数的构造器。

不管上面哪种情况,当调用子类构造器来初始化子类对象时,父类构造器总会在子类构造器之前执行∶不仅如此,执行父类构造器时,系统会再次上溯执行其父类构造器…·依此类推,创建任何 Java 对象,最先执行的总是 java.lang.Obiect 类的构造器。

方法重写

方法的重写要遵循"两同两小一大"规则

"两同"即方法名相同、形参列表相同;

"两小"指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;

"一大"指的是子类方法的访问权限应比父类方法的访问权限更大或相等。

尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法

单例类(Singleton)

只能创建一个对象

3

final类

final修饰的类不能有子类

不可变类

不可变(immutable)类的意思是创建该类的实例后,该实例的实例变量是不可改变的。Java 提供的8个包装类和 java.lang.String类都是不可变类,当创建它们的实例后,其实例的实例变量不可改变。

九、接口

  • 接口不是类,而是对希望符合这个接口的类的一组需求
  • 接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类
  • 接口中的方法都为public
  • 接口里的成员变量只能且默认是public static final修饰
  • 默认方法—为接口方法提供一个默认实现,如 defalut int compareTo(T other){return 0;}
  • 一个类实现的接口和继承的类中方法冲突时,只考虑超类方法;接口方法冲突时必须覆盖这个方法
  • 从某个角度来看,接口可被当成一个特殊的类,因此一个 Java 源文件里最多只能有一个 public 接口,如果一个Java 源文件里定义了一个public 接口,则该源文件的主文件名必须与该接口名相同。

十、lambda表达式

1.语法

1
2
3
4
5
6
7
8
(Type o1, Type o2)->{.......}
()->{.......}
(Type o)->{......}
//如果可以推导出一个lambda表达式的参数类型,则可以忽略其类型
(o)->{......}
(o1,o2)->{.........}
//只有一行可以省略{}
(o1,o2)->o1[1]-o2[1]

2、函数式接口

2

函数式接口举例

1

lambda表达式的目标类型必须是函数式接口(Object也不行),但同样的 Lambda 表达式的目标类型完全可能是变化的——唯一的要求是,Lambda 表达式实现的匿名方法与目标类型(函数式接口)中唯一的抽象方法有相同的形参列表。


3、方法引用

情况 解释 举例
object::instanceMethod 等价于向方法传递参数的lambda表达式 System.out::println等价于x->System.out.println(x)
Class::instanceMethod 第一个参数成为方法的隐式参数 String::compareTo等价于x.compareTo(y)
Class::staticMethon 所有参数都传递到静态方法中 Math::pow等价于Math.pow(x,y)

4.构造器引用

  • int[]::new等价于x->new iny[x]
  • 標題: Java预习
  • 作者: sdjasj
  • 撰寫于: 2022-02-08 20:50:31
  • 更新于: 2022-07-18 09:29:38
  • 連結: https://redefine.ohevan.com/2022/02/08/Java预习/
  • 版權宣告: 本作品采用 CC BY-NC-SA 4.0 进行许可。
 留言