Person person = new Person();
Class clazz = person.getClass();
Person.class;
得到Class对象后,我们就可以调用:
getDeclaredMethods()获取方法
getDeclaredFileds()获取属性
getDeclaredConstructors()获取构造方法
import (static) package.ClassName.*;
- 导入类中的静态方法
这样可以直接使用,比如:导入后,不用再Collectors.counting(),直接counting()即可;再比如调用静态字段,System中的out,我们直接用out控制PrintStream中的方法就可以了…
注意:当导入两个及以上存在同样方法时候,调用时候记得带上类名,不然会引起编译器错误。
- 动态绑定==》多态
- 静态绑定==》成员变量、静态变量、静态方法、私有方法都是静态绑定——调用的是声明类型中(父类的)
public class nullText {
public static void main(String[] args) {
Animal animal = null;
animal.eat();//输出:Eating
}
}
class Animal{
public static void eat(){
System.out.println("Eating");
}
}
- 抽象类可以包含部分方法的实现,jdk8后接口中引入了默认(default)方法,所以这也不咋能称的上是接口的劣势;
- Java中是单继承,类只能单独继承抽象类,但可以实现多个接口,并且可以实现Mixin类型(Mixin的介绍),引用Mixin一般是拓展一些功能。
- 具体类可从抽象类自动得到这些方法的缺省实现(如适配器)。
- 类初始化包含执行的静态初始化语句,以及类中声明的static字段(类变量)的初始化语句;接口的初始化包含执行接口中声明的字段(常量)的初始化语句。
- 初始化一个类前,如果没有初始化过它的超类,必须先初始化其超类,但是不会初始化由该类实现的接口;在初始化一个接口之前,也不会初始化该接口的超接口。
- 以下情况的任意一种情况第一次发生之前,将立即初始化类或接口类型 T:
🎈T 是一个类,并且创建 T 的一个实例;
🎈T 是一个类,并且调用 T 声明的一个静态方法;
🎈使用 T 声明的一个静态字段,并且该字段不是一个常变量(final static int i=1;不行。final static int i = Text.out(“i”,2);行。)
//注意这里调用的是 T 声明的一个静态方法
class Animal{
public static int age = 3;
}
class Bird extends Animal{
static{
System.out.println("I'm a small bird~");
}
}
public class Text{
public static void main(String... args){
System.out.println(Bird.age);
}
}
//这里只会输出:
3
这是因为age是Animal中的静态字段,所以不会初始化Bird类
🎈 T 是一个顶级类,并且执行了一条从词汇上嵌套在T内的 assert 语句;
🎈 调用类Class及包java.lang.reflect 中的某些反射方法,也会引起类或接口的初始化(比如
Class.forName(String XX);)
❗任何其他情况,都不会对类或接口进行初始化了。
首先说明,默认方法是接口中的,也就是说Map的实现类中是没有的。
public class MapforEach {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("shabi",88);
map.put("xx",34);
map.put("vv",83);
map.put("dd",99);
map.forEach((name,score)-> System.out.println("name = " + name + ",score = " + score));
//name = xx,score = 34
//name = vv,score = 83
//name = dd,score = 99
//name = shabi,score = 88
}
}
static
Map.Entry entry(K k, V v) 返回包含给定键和值的不可修改的Map.Entry 。
有了它我们存取元素可以与其它集合联系一块了:
public class entry {
public static void main(String[] args) {
List<Map .Entry<String,Integer>> list = new ArrayList<>();
list.add(Map.entry("shabi",99));
list.add(Map.entry("xiaosan",88));
list.add(Map.entry("bendan",77));
list.stream()
.forEach(System.out::println);
//shabi=99
//xiaosan=88
//bendan=77
}
}
static
Map ofEntries(Map.Entry extends K,? extends
V>… entries)返回包含从给定条目中提取的键和值的不可修改的映射。
可算是完美配套;这样使得键值对隔哪哪都能用了。
public class ofEntries {
public static void main(String[] args) {
Map<String,Integer> map =
Map.ofEntries(Map.entry("dd",77),Map.entry("mm",55),Map.entry("aa",34));
map.forEach((key,value)-> System.out.println("key = " + key + ",value = " + value));
//key = dd,value = 77
//key = mm,value = 55
//key = aa,value = 34
}
}
❤️❤️注意:从输出我们可以看出,里面是无序的。
还有就是采用这种静态方法entry是无法改变的,就比如用replace,还是说Map.Entry中的setValue啊,都是不可以的
default V replace(K key, V value)
仅当指定键当前映射到某个值时,才替换该条目的条目。
这个就及其的方便了,以前怎么处理,要么把那个删掉再重新加,要么用entrySet变成Set集合,然后找到那个再去掉setValue方法,真麻烦,现在好了,一步到位!
public class replaceMap {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("shabi",88);
map.put("xx",34);
map.put("vv",83);
map.put("dd",99);
Integer res = map.replace("shabi",77);
System.out.println("res = " + res); //res = 88
System.out.println("shabi = " + map.get("shabi"));//shabi = 77
Integer res2 = map.replace("xmq",99);
System.out.println("res2 = " + res2);//null
}
}
找到那个key键返回原来的值,没找到就返回null。
❤️default boolean replace(K key, V oldValue, V newValue) 仅当前映射到指定值时,才替换指定键的条目。
❤️default boolean remove(Object key, Object value) 仅当指定键当前映射到指定值时才删除该条目的条目。
❤️default V putIfAbsent(K key, V value) 如果指定的键尚未与值关联(或映射到 null ), null其与给定值关联并返回 null ,否则返回当前值。
咱先来个Map汇总:
HashMap:线程不安全,是根据key的哈希值来存取元素,是无序的
LinkedHashMap:依赖HashMap,线程不安全,但它记录了插入顺序,是有序的
TreeMap:有序的,默认按键值的升序排序,读取时候是线程安全的,修改就不行咯,和TreeSet一样
HashTable:功能类似HashMap,线程安全
有序无序就上面写的咯,Map是个接口,根据需要选择它的实现类进行操作。
实际上除了TreeMap和LinkedHashMap会涉及顺序,其他一般是无序的.