java基础(泛型,枚举,反射)

告别信号干扰!用Altium Designer 19搞定4层/6层PCB叠层设计的保姆级流程 本文详细介绍了如何使用Altium Designer 19进行4层/6层PCB叠层设计,解决信号干扰问题。通过实际案例和系统方法论,涵盖高速数字电路、混合信号系统等典型场景的设计优化,帮助硬件工程师和学生掌握电磁兼容(EMC)与信号完整性(SI)的核心技术。 阅读详情

2 泛型

泛型是JDK1.5及以上才可以使用的特性/语法,它的本质是 类型参数化(Parameterized by types).

2.1 概述

在声明一个类、接口、方法的时候,需要涉及到到一个问题:要给属性确定一个类型,或者给方法的返回值确定一个类型,或者给方法的参数确定一个类型。

之前,定义类、接口、方法的时候,上面所描述的类型都是直接写死,不会变化的。

public class Point{
    int x;
    int y;
}

Point类表示一个坐标点,它的的俩个属性x坐标和y坐标的类型是int,这个int是在定义Point类的时候就已经写好了,并且不会自动改变。

现在,希望Point类中的x属性和y属性的类型变的灵活一点,可以在将来使用的时候,临时通过传参的方式,来确定属性x和y的具体类型。

修改Point类的代码,添加泛型参数T:

public class Point<T>{
    T x;
    T y;
}

注意,T是泛型参数,表示一种数据类型,具体是什么类型,需要将来使用Point的时候进行传参来确定

注意,如果将来Point在使用的时候,没有给泛型参数T传值,那么T默认就表示为Object类型

注意,T是泛型参数的名字,也就是相当于形参,名字随便起,但是一般用一个有意义的大写字母

Point<T>类的使用:

public static void main(String[] args) {
    //p1对象中x和y的属性类型都是Integer
    Point<Integer> p1 = new Point<Integer>();
    p1.x = 1;
    p1.y = 2;
    
    //p2对象中x和y的属性类型都是String
    Point<String> p2 = new Point<String>();
    p2.x = "1";
    p2.y = "2";
    
    //p3对象中x和y的属性类型都是Object
    Point p3 = new Point();
    p3.x = new Object();
    p3.y = new Object();
    
}

可以看出,Point类的中x和y属性的类型,是可以根据我们在使用时所传的参数,进行临时变化的。

如果没有传这个泛型参数,那么这个参数T就默认是Object类型

注意,给泛型参照传的值,只能是引用类型,不能是基本类型:Point<int>编译报错

在类上面添加泛型参数后,在类中的任何可以使用类型的地方,都可以先使用这个泛型参数:

class Point<T>{
    private T x;
    private T y;

    public Point(){}

    public Point(T x, T y) {
        this.x = x;
        this.y = y;
    }

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }
}

思考,为什么泛型也叫做 类型参数化(Parameterized by types)

2.2 集合的泛型

了解泛型的意思之后,接下来可以再看下之前学习过的集合中的泛型:

public interface Collection<E>{
    
    boolean add(E e);
    
}

Collection是一个泛型接口,泛型参数是E,在接口中,add方法的参数类型也使用了E。

那么就说明在使用Collection接口的时候,如果没有给泛型参数传值,那么这个E就默认表示为Object,add方法就可以接收任意类型的对象。

public static void main(String[] args) {
    //没有给泛型参数传值,那么泛型默认表示为Object类型
    Collection c = new ArrayList();
    c.add("hello1");
    c.add("hello2");
    c.add("hello3");
    c.add(1);

    for(Object obj:c){
        String str = (String) obj;
        System.out.println(str);
    }
    
}

//运行结果:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    
    

在这种情况下,集合中如果存储的数据类型不一致,就会在强制转换的时候出现类型转换异常

如果在使用Collection接口的时候,给泛型参数指定了具体类型,那么就会防止出现类型转换异常的情况,因为这时候集合中添加的数据已经有了一个规定的类型,其他类型是添加不进来的。

public static void main(String[] args) {
    Collection<String> c = new ArrayList<String>();
    c.add("hello1");
    c.add("hello2");
    c.add("hello3");
    //编译报错,add(E e) 已经变为 add(String e)
    //int类型的数据1,是添加不到集合中去的
    //c.add(1);

    for(String str : c){
        System.out.println(str);
    }
}

可以看出,传入泛型参数后,add方法只能接收String类型的参数,其他类型的数据无法添加到集合中,同时在遍历集合的时候,也不需要我们做类型转换了,直接使用String类型变量接收就可以了,JVM会自动转换的

Collection<String> c = new ArrayList<String>();

可以简写成:

Collection<String> c = new ArrayList<>();

Map接口使用泛型:

public interface Map<K,V>{
    V put(K key, V value);
    Set<Map.Entry<K, V>> entrySet();
}
public static void main(String[] args) {
    Map<Integer,String> map = new HashMap<>();
    
    //根据泛型类型的指定,put方法中的key只能是Integer类型,value只能是String类型
    map.put(1,"hello1");
    map.put(2,"hello2");
    map.put(3,"hello3");
    map.put(4,"hello4");
	
    //根据上面列出的源码可知,当前指定Map的泛型类型为:Map<Integer,String> map
    //entrySet方法返回的类型就应该是Set<Map.Entry<Integer, String>>
    Set<Map.Entry<Integer, String>> entrySet = map.entrySet();

    for(Map.Entry entry:entrySet){
        System.out.println(entry.getKey()+" : "+entry.getValue());
    }

}

2.3 泛型的种类

java中的泛型分三种使用情况:

  • 泛型类
  • 泛型接口
  • 泛型方法

泛型类,如果泛型参数定义在类上面,那么这个类就是一个泛型类

在类中,就可以使用这个T来代表某一个类型,这个类型具体是什么将来使用的时候再传参确定

public class Point<T>{...}

public static void main(String[] args){
    Point<String> p = new Point<>();
}

泛型接口,如果泛型参数定义在接口上面,那么这个接口就是一个泛型接口

在接口中,就可以使用这个T来代表某一个类型,这个类型具体是什么将来使用的时候再传参确定

public interface Action<T>{...}

public static void main(String[] args){
    //创建匿名内部类
    Action<String> a = new Action<>(){
        //...
    };
}

泛型方法,如果泛型参数定义在方法上面,那么这个方法就是一个泛型方法

public class Test{
    public <T> T test(T t){
        //..
    }
}

public static void main(String[] args){
    Test t = new Test();
    String str = t.test("hello");
    Integer i = t.test(1);
    Double d = t.test(10.5D);
}

可以看出,调用test方法时候,我们传什么类型的参数,test方法的返回类型就是什么类型的。

这种效果,在不使用泛型的情况下,是不可能实现的。

2.4 泛型的类型

先看俩种错误的情况:

//编译通过
//父类型的引用,指向子类对象
Object o = new Integer(1);

//编译通过
//Object[]类型兼容所有的【引用】类型数组
//arr可以指向任意 引用类型 数组对象
Object[] arr = new Integer[1];

//编译失败
//注意,这个编译报错,类型不兼容
//int[] 是基本类型数组
Object[] arr = new int[1];

//编译失败
//错误信息:ArrayList<Integer>无法转为ArrayList<Object>
//在编译期间,ArrayList<Integer>和ArrayList<Object>是俩个不同的类型,并且没有子父类型的关系
ArrayList<Object> list = new ArrayList<Integer>();

注意,=号俩边的所指定的泛型类型,必须是要一样的
注意,这里说的泛型类型,指的是<>中所指定的类型

虽然Integer是Object的子类型,但是ArrayList<Integer>和ArrayList<Object>之间没有子父类型的关系,它们就是俩个不同的类型

所以,

Object o = new Integer(1);编译通过

ArrayList<Object> list = new ArrayList<Integer>();编译报错

也就是说,俩个类型,如果是当做泛型的指定类型的时候,就没有多态的特点了

2.5 通配符

观察下面代码:

public void test1(Collection<Integer> c){

}

public void test2(Collection<String> c){

}

public void test3(Collection<Object> c){

}

test1方法【只能】接收泛型是Integer类型的集合对象
test2方法【只能】接收泛型是String类型的集合对象
test3方法【只能】接收泛型是Object类型的集合对象

原因:由于泛型的类型之间没有多态,所以=号俩边的泛型类型必须一致

在这种情况下,就可以使用通配符(?)来表示泛型的父类型:

public void test(Collection<?> c){

}

注意,这时候test方法中的参数类型,使用了泛型,并且使用问号来表示这个泛型的类型,这个问号就是通配符,可以匹配所有的泛型类型

test方法可以接收 泛型是任意类型的 Collection集合对象

public static void main(String[] args){
    Test t = new Test();
    t.test(new ArrayList<String>());
    t.test(new ArrayList<Integer>());
    t.test(new ArrayList<Object>());
    t.test(new ArrayList<任意类型>());
}

使用通配符(?)所带来的问题:

Collection<?> c;
        
c = new ArrayList<String>();

//编译报错
//因为变量c所声明的类型是Collection,同时泛型类型是通配符(?)
//那么编译器也不知道这个?将来会是什么类型,因为这个?只是一个通配符
//所以,编译器不允许使用变量c来向集合中添加新数据。
c.add("hello");

//编译通过
//但是有一个值是可以添加到集合中的,null
//集合中一定存的是引用类型,null是所有引用类型共同的一个值,所以一定可以添加进去。
c.add(null);

虽然使用通配符(?)的集合,不能再往其中添加数据了,但是可以遍历集合取出数据:

public static void main(String[] args) {

    ArrayList<String> list = new ArrayList<>();
    list.add("hello1");
    list.add("hello2");
    list.add("hello3");
    list.add("hello4");

    Collection<?> c = list;
    
    //编译报错
    //c.add("hello5");

    for(Object obj : c){
        System.out.println(obj);
    }

}

2.6 泛型边界

在默认情况下,泛型的类型是可以任意设置的,只要是引用类型就可以。

如果在泛型中使用extends和super关键字,就可以对泛型的类型进行限制。即:规定泛型的上限和下限。

泛型的上限:(ps:不可添加元素,但可以删除遍历已有元素)

  • 例如:List<? extends Number> list

  • 将来引用list就可以接收泛型是Number或者Number子类型的List集合对象

public static void main(String[] args) {

    List<? extends Number> list;
    //list可以指向泛型是Number或者Number【子】类型的集合对象
    list = new ArrayList<Number>();
    list = new ArrayList<Integer>();
    list = new ArrayList<Double>();

    //编译报错,因为String不是Number类型,也不是Number的子类型
    //list = new ArrayList<String>();


}

能表示数字的类型都是Number类型的子类型,例如Byte Short Integer Long等

泛型的下限:(ps:可以添加元素,也可以删除,遍历已有元素)

  • 例如:List<? super Number> list

  • 将来引用list就可以接收泛型是Number或者Number父类型的List集合对象

public static void main(String[] args) {

    List<? super Number> list;
    //list可以指向泛型是Number或者Number【父】类型的集合对象
    list = new ArrayList<Number>();
    list = new ArrayList<Serializable>();
    list = new ArrayList<Object>();

    //编译报错,因为String不是Number类型,也不是Number的父类型
    //list = new ArrayList<String>();
    
    //编译报错,因为Integer不是Number类型,也不是Number的父类型
    //list = new ArrayList<Integer>();


}

泛型中extends和super对比:

  • 使用extends可以定义泛型的【上限】,这个就表示将来泛型所接收的类型【最大】是什么类型。可以是这个最大类型或者它的【子类型】。
  • 使用super可以定义泛型的【下限】,这个就表示将来泛型所接收的类型【最小】是什么类型。可以是这个【最小类型】或者它的【父类型】。

extends 限定泛型的上限的使用场景

  1. 在声明泛型类或者泛型接口的时候【可以】使用

    public class Point<T extends Number>{
        private T x;
        private T y;
    }
    
    interface Action<T extends Person>{
        public void test(T t);
    }
    
  2. 在声明泛型方法的时候【可以】使用

    public <T extends Action> void test(T t);
    
  3. 在声明变量的时候【可以】使用

    public class Test{
        public void test(List<? extends Number> list){
    				
    	}
    }
    
    public static void main(String[] args) {
        List<? extends Number> list = new ArrayList<Long>();
        t.test(list);
    }
    

super 限定泛型的下限的使用场景

  1. 在声明泛型类或者泛型接口的时候【不能】使用

    //编译报错
    public class Point<T super Number>{
        private T x;
        private T y;
    }
    //编译报错
    interface Action<T super Person>{
        public void test(T t);
    }
    
  2. 在声明泛型方法的时候【不能】使用

    //编译报错
    public <T super Action> void test(T t);
    
  3. 在声明变量的时候【可以】使用

    public class Test{
        public void test(List<? super Number> list){
    				
    	}
    }
    
    public static void main(String[] args) {
        List<? super Number> list;
    
        list = new ArrayList<Number>();
        list = new ArrayList<Object>();
    
        //假设Student 继承了 Person 
    
        List<? super Student> list;
    
        list = new ArrayList<Student>();
        list = new ArrayList<Pesson>();
        list = new ArrayList<Object>();
    }
    

2.7 类型擦除

泛型类型仅存在于编译期间,编译后的字节码和运行时不包含泛型信息,所有的泛型类型映射到同一份字节码。

由于泛型是JDK1.5才加入到Java语言特性的,Java让编译器擦除掉关于泛型类型的信息,这样使得Java可以向后兼容之前没有使用泛型的类库和代码,因为在字节码(class)层面是没有泛型概念的。

例如,定义一个泛型类Generic是这样的:

class Generic<T> {
    private T obj;

    public Generic(T o) {
        obj = o;
    }

    public T getObj() {
        return obj;
    }
}

那么,Java编译后的字节码中Generic相当于这样的:(类型擦除,变为原始类型Object)

class Generic {
    private Object obj;

    public Generic(Object o) {
        obj = o;
    }

    public Object getObj() {
        return obj;
    }
}

例如,

public static void main(String[] args) {
	
    //编译报错
    //ArrayList<Integer>和new ArrayList<Long>在编译期间是不同的类型
    ArrayList<Integer> list = new ArrayList<Long>();
	
    //但是编译完成后,它们对应的是同一份class文件:ArrayList.class
    ArrayList<Integer> list1 = new ArrayList<Integer>();
	ArrayList<Long> list2 = new ArrayList<Long>();
	System.out.println(list1.getClass() == list2.getClass());//true

}

注意,泛型信息被擦除后,所有的泛型类型都会统一变为原始类型:Object

例如,

//编译报错
//因为在编译后,泛型信息会被擦除
//那么一个类会就存在了俩个一样的方法
//public void run(List list)
public class Test {

    public void run(List<String> list){

    }

    public void run(List<Integer> list){

    }

}

可以看出,Java的泛型只存在于编译时期,泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。

但是在编译成功后,所有泛型信息会被擦除,变为原始类型Object

3 枚举

3.1 概述

枚举,是JDK1.5引入的新特性,可以通过关键字enum来定义枚举类。

枚举类是一种特殊的类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口。

但是枚举类不能继承其他类.

public enum Color {
    BLACK, WHITE
}

public enum Color,表示这是一个枚举类型,名字叫Color

BLACK, WHITE表示这个枚举类型有俩个固定的对象,一个叫BLACK,另一个叫WHITE

简单的使用这个枚举类型:

public static void main(String[] args) {
    //声明枚举类型的引用
    Color c;
    
    //引用指向对象
    c = Color.BLACK;
    //默认调用toString方法,父类中重写了toString方法,返回枚举对象的名字
    System.out.println(c);
	
    //引用指向对象
    c = Color.WHITE;
    //默认调用toString方法,父类中重写了toString方法,返回枚举对象的名字
    System.out.println(c);

}
//运行结果:
BLACK
WHITE

使用javap命令对Color.class文件进行反向解析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t4nVUlGZ-1597894256191)(corejava-day12.assets/image-20200805231242306.png)]

从运行结果中,可以看出:

  • 枚举其实也是一种类,同时还是一个final修饰的类

  • 枚举类型都会默认继承一个父类型:java.lang.Enum,这还是一个抽象的泛型类

    public abstract class Enum<E extends Enum<E>>{}
    
  • 枚举中所定义的对象,其实就是类里面的public static final修饰的常量,并且这些常量会在静态代码块中做初始化

  • 枚举类型中还一个默认的私有构造器,说明我们在外面并不能自己去创建枚举类型的对象

  • 枚举类型中还有默认添加进来的方法

    values()方法,可以返回这个枚举类型的所有对象,返回类型是数组

    valueOf(String str)方法,通过一个字符串可以返回枚举对象,这个字符串参数就是枚举对象的名字

  • 枚举类型会从父类中继承过来一些方法(具体可以查看其固定的父类型),例如

    String name(),返回这个枚举对象的名字

    int ordinal(),返回这个枚举对象的编号,默认从0开始

3.2 意义

java中的类,从语法形式上来说,可以创建出一个类的无数个对象。

例如,学生类Student,我们可以创建出10个、20个等不同数量的学生对象,并且从意义讲确实也没有问题,因为实际情况中确实会存在很多不同的学生。

但是这其实还存在另一种情况:一个类的对象,从意义上来说,对象个数是固定的。

例如,Gender这个类,表示人的性别,从语法上来说,可以创建出无数个性别对象,但是从实际意义上看,我们只需要俩个对象就可以了,一个表示男、一个表示女。

那么,在这个时候,我们就需要去对Gender类的对象创建作出限制,不让用户创建很Gender类型的对象,因为如果创建了很多对象,那么会占用内存空间,同时这么多对象也没什么实际意义,最终还是只能表示俩种情况,男和女。

解决这个问题的方式是,可以将Gender定义为一个枚举类型(enum),我们就可以在枚举类型中,提前将这个类型的对象个数和对象名字都固定下来,并且之后的使用中不会改变,也不会再创建其他对象。

例如,

public enum Gender{
	MALE,FEMALE
}

那么,这时候表示性别的类型Gender,就会有且只有俩个对象,MALE和FEMALE

3.3 获取枚举对象

以Gender这个枚举类型为例:

public enum Gender{
	MALE,FEMALE
}

方式一:

public static void main(String[] args){
    //使用类名直接访问类中定义的俩对象
	//最常用的一种方式
	Gender g = Gender.MALE;
    g = Gender.FEMALE;
    
    //可以调用从父类型Enum以及Object中继承过来的方法
    System.out.println(g.name());
	System.out.println(g.ordinal());
    System.out.println(g.toString());
    
}
//运行结果:
MALE
0
MALE

方式二:

public static void main(String[] args){
    //通过字符串参数的改变,可以获取到Gender中的指定的一个对象
    String name = "MALE";
    Gender g = Gender.valueOf(name);
    
    System.out.println(g.name());
	System.out.println(g.ordinal());
    System.out.println(g.toString());
    
}
//运行结果:
MALE
0
MALE

方式三:

public static void main(String[] args){
    //通过字符串确定是哪一个枚举类型
    Class c = Class.forName("com.briup.demo.Genger");
    //通过字符串确定是哪一个名字的枚举对象
    String name = "FEMALE";
    //可以通过改变字符串,获取到java中任何一个枚举类型中的任意一个枚举对象
    Enum g = Enum.valueOf(c,name);
    
    System.out.println(g.name());
	System.out.println(g.ordinal());
    System.out.println(g.toString());
    
}
//运行结果:
FEMALE
1
FEMALE

3.4 枚举中定义属性和方法

在枚举类型中,除了可以指定对象的个数和名称之外,还可以定义属性和方法,例如

public enum Gender{
    MALE,FEMALE;

    private String name;

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
    
    public void test(){
        System.out.println("Gender test...");
    }

    public static void print(String name){
        System.out.println("hello "+name);
    }

}

public static void main(String[] args){
    Gender g = Gender.MALE;

    g.test();

    g.setName("我是男生");
    System.out.println(g.getName());

    Gender.print("jack");

}

注意,枚举类型中的第一行代码,要求一定是指定枚举对象的个数和名字,同时最后面加分号(;)

在这行代码下, 才可以定义枚举类型的属性和方法

3.5 枚举中定义构造器

枚举类型中还可以定义自己的构造器,例如

public enum Gender{
    MALE,FEMALE;

    private String name;

    private Gender(){

    }
    private Gender(String name){
        this.name = name;
    }

    @Override
    public String toString() {
        return "Gender{name="+name+"}";
    }
}

枚举中的构造器,只能使用private修饰,或者不写修饰符,那么默认也是private,同时还可以构造器重载

枚举类型中构造器的调用:

public enum Gender{
	MALE,FEMALE
}

在枚举中,定义对象的时候,就已经默认使用了无参构造器,所以以上代码可以写成如下:

public enum Gender{
	MALE(),FEMALE();
    
    //构造器,默认private修饰
    Gender(){
    	System.out.println("无参构造器被调用");
    }
}

public static void main(String[] args)throws Exception {
    //该代码,可以对Gender.class进行类加载
    Class.forName("com.briup.demo.Gender");
}

//运行结果:
无参构造器被调用
无参构造器被调用

可以 看出,当前Gender.class完成类加载的时候,就会自动调用无参构造器创建对象MALE和FEMALE

因为MALE和FEMALE在枚举类型是使用public static final修饰的俩个静态常量。(javap命令)

也可以调用有参构造器:

public enum Gender{
    MALE("男"),FEMALE("女");

    private String name;
    Gender(){
        System.out.println("无参构造器被调用");
    }
    Gender(String name){
        this.name = name;
        System.out.println("有参构造器被调用");
    }
}

public static void main(String[] args)throws Exception {
    //该代码,可以对Gender.class进行类加载
    Class.forName("com.briup.demo.Gender");
}

//运行结果:
有参构造器被调用
有参构造器被调用

3.6 枚举中定义抽象方法

枚举类型中还可以定义抽象方法,例如

public enum Gender{
    MALE,FEMALE;

    public abstract void test();

}

注意,这时候代码编译会报错。

需要在定义每一个枚举对象的时候,将抽象方法进行实现,因为枚举类型是final修饰的类,不可能有子类型来实现这个抽象方法,所以就必须是自己的对象去实现这个抽象方法,例如:

public enum Gender{
    MALE(){
        @Override
        public void test() {
            System.out.println("男生测试");
        }
    },FEMALE(){
        @Override
        public void test() {
            System.out.println("女生测试");
        }
    };

    public abstract void test();

}

注意,这种写法和匿名内部类的写法很相似, MALE(){...},FEMALE(){...};

3.7 枚举类型实现接口

枚举类型已经有默认的父类型(java.lang.Enum),我们就不能让它在继承其他父类了,但是我们可以让枚举类型实现指定的接口:

public enum Gender implements Action{
    MALE,FEMALE;
}

interface Action{
    void run();
}

注意,这时候代码编译会报错。

需要在枚举类型中,实现接口中的抽象方法,这里有俩种方式:

方式一,在枚举中,统一实现这个接口中的抽象方法:

public enum Gender implements Action{
    MALE,FEMALE;

    @Override
    public void run() {
        System.out.println("枚举中统一实现接口中的抽象方法");
    }
}

interface Action{
    void run();
}

方式二,在每个枚举对象中,分别实现这个接口中的抽象方法:

public enum Gender implements Action{
    MALE(){
        @Override
        public void run() {
            System.out.println("男生对象中,单独实现接口中的抽象方法");
        }
    },FEMALE(){
        @Override
        public void run() {
            System.out.println("女生对象中,单独实现接口中的抽象方法");
        }
    };

}

interface Action{
    void run();
}

3.8 枚举使用总结

对于枚举类型的使用,大多数情况下,我们在枚举中列出它的的每一个对象即可,偶尔会添加几个自定义的属性和方法,并不会写的那么复杂,否则就没什么意义了。

在项目中,只要一个类型的对象个数和名称能固定下来的,就可以考虑使用枚举类型来表示。

思考,除了性别在项目可以定义为枚举类型之外,你还能想到哪些类型可以定义为枚举?

4 反射

4.1 概述

反射是java中提供的一种机制,它允许我们在程序运行的时候,动态获取一个类中的基本信息,并且可以调用类中的属性、方法、构造器。

例如,Student类型

public class Student{
    private String name;
    int age;
    public static int num;

    public Student(){}

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String sayHello(String name){
        return "hello! "+name;
    }

}

我们除了用眼睛看到这个类中有些哪些属性、方法、构造器之外,在代码运行的时候,也可以通过反射机制获取到这个类中的属性、方法、构造器,以及调用它们。

例如,查看类中声明的属性:

public static void main(String[] args)throws Exception {
    Class c = Class.forName("com.briup.demo.Student");

    Field[] fields = c.getDeclaredFields();
    for(Field f : fields){
        System.out.println("属性的修饰符:"+Modifier.toString(f.getModifiers()));
        System.out.println("属性的类型:"+f.getType().getName());
        System.out.println("属性的名称:"+f.getName());
        System.out.println("---------------------");
    }

}
//运行结果:
属性的修饰符:private
属性的类型:java.lang.String
属性的名称:name
---------------------
属性的修饰符:
属性的类型:int
属性的名称:age
---------------------
属性的修饰符:public static
属性的类型:int
属性的名称:count
---------------------

可以看出,即使没有源代码(.java文件),我们也能指定这个类中都声明了哪些属性

同样的,我们也可以使用类似的方式,获取到类中的方法信息和构造器信息,甚至是调用它们

4.2 Class类型

java.lang.Class是API中提供的一个类,它可以表示java中所有的类型,包括基本类型和引用类型。

在之前的学习中,我们也接触过这个类型,Object中的方法getClass方法:

public final native Class<?> getClass();

该方法的返回类型就是Class,所以 obj.getClass();这句代码的含义就是:返回obj引用在运行时所指向对象的实际类型。

使用Class类的对象来表示基本类型:

public static void main(String[] args)throws Exception {

    //这个对象c就代表java中的int类型
    Class c = int.class;

    //判断对象c所代表的类型是否是基本类型
    System.out.println(c.isPrimitive());
    //获取对象c所代表的类型的名字
    System.out.println(c.getName());


}
//运行结果:
true
int

使用Class类的对象来表示类类型:

public static void main(String[] args)throws Exception {

    //这个对象c就代表Student类
    Class c = Student.class;
    System.out.println(c.getName());

}
//运行结果:
com.briup.demo.Student

使用Class类的对象来表示接口类型:

public static void main(String[] args)throws Exception {

    //这个对象c就代表List接口类型
    Class c = List.class;
    System.out.println(c.isInterface());
    System.out.println(c.getName());

}
//运行结果:
true
java.util.List

使用Class类的对象来表示数组类型:

public static void main(String[] args)throws Exception {

    //这个对象c代表数组类型
    Class c;
    c = int[].class;
    c = int[][].class;
    c = Student[].class;
    System.out.println(c.isArray());
    System.out.println(c.getSimpleName());
    //返回组成该数组具体类型是什么
    System.out.println(c.getComponentType().getSimpleName());

}
//运行结果:
true
Student[]
Student

4.3 获取Class对象

在java中,每种类型(基本类型和引用类型)加载到内存之后,都会在内存中生成一个Class类型对象,这个对象就代表这个具体的java类型,并且保存这个类型中的基本信息。

注意,java中的每种类型,都有且只有唯一的一个Class类型对象与之对应!并且在类加载的时候自动生成!

获取基本类型的Class对象:

只有一种方式:Class c = int.class;

获取接口类型的Class对象:

有俩种方式:

  • Class c1 = Action.class;
  • Class c2 = Class.forName("com.briup.demo.Action");

获取数组类型的Class对象:

有俩种方式:

  • Class c1 = int[].class;
  • int[] arr = new int[4]; Class c2 = arr.getClass();
  • Student stu = new Student(); Class c3 = stu.getClass();

获取类类型的Class对象:

有三种方式:

  • Class c1 = Student.class;
  • Class c2 = Class.forName("com.briup.demo.Student");
  • Student stu = new Student(); Class c3 = stu.getClass();

可以看出,获取一个类型Class对象的途径一般有三种

  • 使用类型名称直接获取
  • 使用Class类中的静态方法forName获取
  • 使用对象调用getClass方法获取

4.4 获取类的信息

例如,以Student为例进行操作说明

public class Student implements Action,Mark{
    private String name;
    int age;
    public static int num;

    public Student(){}

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String sayHello(String name){
        return "hello! "+name;
    }

    @Override
    public void run() {

    }

    @Override
    public void star() {

    }
}

interface Action{
    void run();
}
interface Mark{
    void star();
}

例如,获取类的基本信息:

public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();

    //获取类的名字,全限定名
    System.out.println(c.getName());
    //获取类的名字,简单类名
    System.out.println(c.getSimpleName());
    //获取类所属包的名字
    System.out.println(c.getPackage().getName());
    //获取类的修饰符
    System.out.println(Modifier.toString(c.getModifiers()));
    //获取类的父类型的名字
    System.out.println(c.getSuperclass().getName());
    //获取类实现的所有接口
    System.out.println(Arrays.toString(c.getInterfaces()));
    
    Class c2 = Object.class;
    Class c3 = Action.class;
    Class c4 = Mark.class;
    Class c5 = String.class;
    //判断c2代表的类型是不是c代表类型 的父类型
    System.out.println(c2.isAssignableFrom(c));
     //判断c3代表的类型是不是c代表类型 的父类型
    System.out.println(c3.isAssignableFrom(c));
     //判断c4代表的类型是不是c代表类型 的父类型
    System.out.println(c4.isAssignableFrom(c));
     //判断c5代表的类型是不是c代表类型 的父类型
    System.out.println(c5.isAssignableFrom(c));

}
//运行结果:
com.briup.demo.Student
Student
com.briup.demo
public
java.lang.Object
[interface com.briup.demo.Action, interface com.briup.demo.Mark]
true
true
true
false

例如,获取类中声明的属性:

获取类中的public修饰的属性,也包含从父类中继承过来的public属性

  • Field[] getFields()

  • Field getField(String name)

获取类中声明的属性(包含私有的),但是不能获取从父类中继承过来的属性

  • Field[] getDeclaredFields()
  • Field getDeclaredField(String name)
public static void main(String[] args)throws Exception {
    Class c = Class.forName("com.briup.demo.Student");

    Field[] fields = c.getDeclaredFields();
    for(Field f : fields){
        System.out.println("属性的修饰符:"+Modifier.toString(f.getModifiers()));
        System.out.println("属性的类型:"+f.getType().getName());
        System.out.println("属性的名称:"+f.getName());
        System.out.println("---------------------");
    }

}
//运行结果:
属性的修饰符:private
属性的类型:java.lang.String
属性的名称:name
---------------------
属性的修饰符:
属性的类型:int
属性的名称:age
---------------------
属性的修饰符:public static
属性的类型:int
属性的名称:count
---------------------

注意,java.lang.reflect.Field表示类中的属性

例如,获取类中声明的方法:

获取当前类中的public方法,包含从父类中继承的public方法

  • Method[] getMethods()
  • Method getMethod(String name, Class<?>... parameterTypes)

获取当前类中声明的方法(包含私有的),但是不能获取从父类中继承过来的方法

  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();
	
     //获取类中声明的所有方法
    Method[] methods = c.getDeclaredMethods();
    
    for(Method m : methods){
        //获取方法的修饰符
        System.out.println(Modifier.toString(m.getModifiers()));
        //获取方法的返回类型
        System.out.println(m.getReturnType().getSimpleName());
        //获取方法的名字
        System.out.println(m.getName());

        System.out.println("方法参数个数:"+m.getParameterCount());
        //获取方法的参数列表
        Class[] paramArr = m.getParameterTypes();
        //输出方法的参数列表
        System.out.println("\t"+Arrays.toString(paramArr));

        //获取方法所抛出的异常类型
        Class[] exceptionArr = m.getExceptionTypes();
        System.out.println("方法抛出异常个数:"+exceptionArr.length);
        //输出方法所抛出的异常列表
        System.out.println("\t"+Arrays.toString(exceptionArr));
        System.out.println("-------------------------------");
    }

}

//运行结果:
public
void
run
方法参数个数:0
	[]
方法抛出异常个数:0
	[]
-------------------------------
public
String
getName
方法参数个数:0
	[]
方法抛出异常个数:0
	[]
-------------------------------
public
void
setName
方法参数个数:1
	[class java.lang.String]
方法抛出异常个数:0
	[]
-------------------------------
public
String
sayHello
方法参数个数:1
	[class java.lang.String]
方法抛出异常个数:0
	[]
-------------------------------
public
void
star
方法参数个数:0
	[]
方法抛出异常个数:0
	[]
-------------------------------

注意,java.lang.reflect.Method表示类中的方法

例如,获取类中声明的构造器:

获取当前类中的public构造器

  • public Constructor<?>[] getConstructors()
  • public Constructor<T> getConstructor(Class<?>... parameterTypes)

获取当前类中的所有构造器,包含私有的

  • public Constructor<?>[] getDeclaredConstructors()
  • public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();

    //获取类中所有的public构造器
    Constructor[] constructors = c.getConstructors();

    for(Constructor constructor:constructors){

        //构造器的修饰符
        System.out.println(Modifier.toString(constructor.getModifiers()));
        //构造器的名字
        System.out.println(constructor.getName());

        //构造器的参数列表
        Class[] paramList = constructor.getParameterTypes();
        System.out.println(java.util.Arrays.toString(paramList));

        //构造器的抛出异常
        Class[] exceptionList = constructor.getExceptionTypes();
        System.out.println(java.util.Arrays.toString(exceptionList));

        System.out.println("-----------------------------");
    }

}
//运行结果:
public
com.briup.demo.Student
[]
[]
-----------------------------
public
com.briup.demo.Student
[class java.lang.String, int]
[]
-----------------------------

注意,java.lang.reflect.Constructor表示类中的方法

4.5 反射访问属性

public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();

    //获取类中名字叫name的属性
    Field f1 = c.getDeclaredField("name");
    //设置私有属性可以被访问,否则报错
    f1.setAccessible(true);
    //用反射的方式,给指定对象的name属性赋值
    //相当于之前的stu.name = "tom";
    f1.set(stu,"tom"); 
    //用反射的方式,获取这个属性的值
    //相当于之前的stu.name
    System.out.println(f1.get(stu));

    System.out.println("----------------------");

    //获取类中名字叫age的属性
    Field f2 = c.getDeclaredField("age");
    //用反射的方式,给指定对象的age属性赋值
    //相当于之前的stu.age = 20;
    f2.set(stu,20);
    //用反射的方式,获取这个属性的值
    //相当于之前的stu.age
    System.out.println(f2.get(stu));

    System.out.println("----------------------");

    //获取类中名字叫num的属性
    Field f3 = c.getDeclaredField("num");
    //用反射的方式,给静态属性num赋值,不需要对象
    //相当于之前的Student.num = 99;
    f3.set(null,99);
    //用反射的方式,获取这个静态属性的值,不需要对象
    //相当于之前的Student.num
    System.out.println(f3.get(null));


}

4.6 反射调用方法

public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();

    //获取类中的toString方法,没有参数,这是从父类继承的方法
    Method m1 = c.getMethod("toString", null);

    //反射的方式,调用stu对象中的这个方法,没有参数,并接收执行结果
    //相当于之前的:Object result = stu.toString();
    Object result = m1.invoke(stu,null);

    //输出执行结果
    System.out.println(result);

    System.out.println("-------------------");

    //获取类中的sayHello方法,需要一个String类型的参数,这是自己定义的方法
    Method m2 = c.getMethod("sayHello", String.class);

    //反射的方式,调用stu对象中的这个方法,参数是"tom",并接收执行结果
    //相当于之前的:Object result = stu.sayHello("tom");
    result = m2.invoke(stu,"tom");

    //输出执行结果
    System.out.println(result);


}`

注意,public Object invoke(Object obj, Object... args)

  • obj,表示要调用哪个对象的方法,如果是静态方法,可以传null
  • args,可变参数,表示要调用的方法的参数列表

m.invoke(obj,null)中的m,就是通过Class对象获取到的类中的某一个指定的方法

4.7 反射创建对象

使用反射的方式可以创建对象,也就是需要反射调用构造器。

例如,反射调用类中无参构造器创建对象

public static void main(String[] args)throws Exception {
    Class c = Student.class;

    //默认调用类中的无参构造器来创建对象
    //相当于之前的:Object obj = new Student();
    Object obj = c.newInstance();
    System.out.println(obj);

}

例如,反射调用类中有参构造器创建对象

public static void main(String[] args)throws Exception {
    Class c = Student.class;

    //获取类中的俩参构造器
    Constructor constructor = c.getConstructor(String.class, int.class);

    //调用有参构造器创建对象,并传入对应的参数值
    //相当于之前的:Object obj = new Student("tom",20);
    Object obj = constructor.newInstance("tom",20);

    System.out.println(obj);


}

思考,使用反射的方式访问属性、调用方法、创建对象,和普通方式比较起来,有什么优势?

如果属性和方法以及构造器都是私有的,可以通过反射的方式直接去访问或创建对象,如果是普通方式,

私有方法和属性只能在本类中调用。

练习:编写一个方法,方法中可以调用到任意一个类中的任意一个无参方法

public Object test(String className,String methodName) throw Exception{
    //如何实现?
    //得到Class对象
    Class.forName(className);
    //通过Class对象调用无参构造器去创建对象
    Object obj = c.newInstance();
    //通过对象得到方法
    Method method = c.getDeclareMethods(methodName);
    //设置方法可调用
    methos.setAccessible(true);
    
    //调用该方法并传参
    Object jj = method.invoke(obj);
    //返回值
    return jj;
}
Data-Structures-and-Algorithm-Analysis-in-Java.pdf 作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo... 立即下载

相关推荐

【补充:脑电绘图教程 2】如何手动去除ICA伪迹分量

ICA可以将脑电信号分解为多个IC分量,由每个分量的平均功率地形图可以看出哪些分量属于伪迹,去除伪迹分量后,即可得到“干净”的脑电信号。本教程主要总结如何人工识别出ICA伪迹分量,不涉及ICA的原理讲解。本教程的主要知识来源是ICLabel官网ICLabel致力于自动识别IC分量属于哪种伪迹,并标记伪迹占比,可以在eeglabel中很方便地使用。ICLabel给出了几种常见伪迹的特点,本教程主要是根据ICLabel给出伪迹特点,对自己的数据集手动去除伪迹,以更深入了解自己数据集的质量和伪迹特点。

qq_40735196的博客 4230

Java知识整理——反射、枚举、注解、泛型

(1)、类的加载 当程序要执行某个类的时候,如果这个类还没有被加载到内存中,系统会通过加载、链接、初始化三步来实现对这个类的初始化。 加载: 加载就是把class文件读入到内存中,并对应的创建一个Class对象,任何类被使用的时候系统都会建立一个Class对象 链接: 验证 内部结构是否是正确的,并且和其他类协调一致 准备 负责为类的静态成员分配内存空间,并设置默认初始化值 解析 把类的二进制...

胖子 558

mac(apple silicon)arm64安装spm12详细教程

3.下载matlab runtime R2023b for macOS (macA64),注意必须下载这个,只下载matlab是不可以的。默认安装目录是/Applications/MATLAB/MATLAB_Runtime/R2023b。注意最后的命令,路径根据自己的matlab_runtime安装位置进行调整,然后就可以安装成功了。5. 解压spm12.zip,解压后将文件夹拖到应用程序下(Applications)2.下载spm12,这个版本可兼容mac芯片!6.打开mac终端,输入。

weixin_62332001的博客 2019

泛型(包装类),反射,枚举,lambda表达式

就是适用于许多许多类型,从代码上讲,就是对类型实现了参数化那么泛型的本质是什么呢?在java中所有的类都继承于Object这个父类所以我们就可以在通过创建一个Object的数组。虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类 型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。语法:class泛型类名称类型形参列表。

Cheer_RIO的博客 454

Aitoearn内容营销的最佳开源 AI 代理,创建 · 发布 · 互动 · 副业一站式平台,支持渠道:抖音、小红书(红点)、微信通道、快手、哔哩哔哩、微信公众号、抖音等等

Aitoearn内容营销的最佳开源 AI 代理,创建 · 发布 · 互动 · 副业一站式平台,支持渠道:抖音、小红书(红点)、微信通道、快手、哔哩哔哩、微信公众号、抖音等等

struggle2025的博客 1749

深信服桌面云实战:从零部署到高效运维的配置全景指南

本文详细介绍了深信服桌面云从零部署到高效运维的全流程配置指南,涵盖硬件规划、平台部署、虚拟桌面发布、终端管理及性能优化等关键环节。特别强调了双万兆网络架构、分布式存储配置和智能调度功能的应用,帮助用户实现高性能、高可用的虚拟桌面环境。

weixin_28568819的博客 395

java第十一章 枚举与泛型

11.1 枚举 枚举是一种数据类型,它是一系列具有名称的常量的集合。 11.1.1 使用枚举类型设置常量 定义常量的常用形式: public interface Contants { public static final int Constants_A=1; public static final int Constants_B=12; } ...

m0_61790579的博客 1892

I2C通信协议SCL与SDA引脚特性:核心要点总结

深入讲解I2C通信协议中SCL和SDA引脚的工作机制与电气特性,帮助理解i2c通信协议的稳定传输原理,掌握上拉电阻配置与信号时序控制要点。

weixin_42103128的博客 2727

【JAVA-枚举和泛型】

枚举类型是将常量封装在类或接口中,本质上还是以类的形式存在。泛型可以减少代码量,还不会因为对象置于某个容器中而失去其类型。

m0_48590589的博客 539

【Unity实战】实现最完美最简单的UI适配方案,背景压缩或者拉伸变形解决方案,手机刘海屏适配,适配不同分辨率,不同尺寸,不同设备。

这期来讲一个简单的UI设计方案,很多同学可能搞不懂锚点、轴心这些概念,导致做好的UI在别人的设备上,乱跑或者是重叠,或者是参加游戏老发时间比较紧来不及做适配,都可以来试试这个方法,通过填充边框来保持游戏画面的原始比例,所以它的缺点也很明显,在一些移动设备上会浪费比较大的显示面积。 unity不同设备UI变形? UI在不同设备上如何适配?

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 3647

机器人常用坐标系详解:原理、获取方法及实战实例

本文系统阐述了机器人四大核心坐标系(世界、基、工具、工件)的原理与标定方法。世界坐标系提供全局参考基准,基坐标系绑定机器人本体,工具坐标系定义末端执行器位置,工件坐标系则锁定作业对象位置。通过齐次变换矩阵实现各坐标系间的关联转换。重点介绍了三类标定技术:手动设定法(世界坐标系)、三点/六点法(工具TCP标定)和视觉识别法(工件标定),并以工业机械臂上下料为例演示了完整应用流程。随着技术发展,自动化标定、动态坐标系等新趋势将进一步提升机器人作业精度与效率。

start_up_go的博客 512

Java编程学习笔记---枚举类型与泛型

Object类为最上层的父类,很多程序员为了使程序更为通用,设计程序时通常使传入的值与返回的值都以Object类型为主。当需要使用这些实例时,必须正确地将该实例转换为原来的类型,否则在运行时将会发生ClassCastException异常。为了提前预防这种问题,Java提供了泛型机制。类名<类型参数T, 类型参数T2, .... , 类型参数Tn>其中,T是泛型的名称,代表某一种类型。开发者在创建该类对象时需要指定T所代表哪种具体的类型。如果不指定具体类型,T则采用Object类型。

没技术的博客 940

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【Java基础】泛型+反射+枚举+Lambda表达式 知识点总结

本文重点介绍Java基础:泛型、反射、枚举、Lambda表达式知识点总结。

爱干饭的猿的博客 3141

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

对java泛型、枚举、注解以及反射的基础学习

泛型、枚举、注解和反射的初步了解 2 泛型 泛型是JDK1.5及以上才可以使用的特性/语法,它的本质是 类型参数化(Parameterized by types). 2.1 概述 在声明一个类、接口、方法的时候,需要涉及到到一个问题:要给属性确定一个类型,或者给方法的返 回值确定一个类型,或者给方法的参数确定一个类型 之前,定义类、接口、方法的时候,上面所描述的类型都是直接写死,不会变化的 public class Point{ int x; int y; } Point 类表示一个坐

weixin_45273750的博客 269

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java基础—枚举、注解、泛型、反射

一 、注解(Annotation) 注解就是代码里的特殊标记,可以在编译、类加载、运行时读取,并执行相应的处理。注解可以像修饰符一样使用,用于修饰包、类、构造器、方法、成员变量、参数等。 一定程度上:框架 = 注解 + 反射+设计模式 1.1 jdk内置的三个注解 @Override 重写父类方法 @Deprecated 标注已经过时的方法 @SuppressWarnings 抑制编译器警告 @SuppressWarnings("unuserd") 1.2 自定义注解 ...

光天化日红裤衩 161

JAVA基础篇(四)——反射、枚举、泛型

** 反射** 反射是java语言的一个特性,通过动态编译确定类型,绑定对象,对内部的成员进行操作, 作用 在运行时判断一个对象所属的类 在运行时获取类的对象 在运行时访问java对象的属性、方法、构造方法等 优缺点 可以实现动态创建对象和编译,灵活性强,但对性能有影响 Ioc 是一个容器,在容器里要产生的对象都在配置文件中给出定义,然后利用编程语言提供的反射机制,根据配置文件中给出的类名生成相应的对象。 枚举类型 是由一组固定的常量组合成合法的类型,用来简化代码,方便操作 应用场景 定义变量(如周天、四季

Superwwz的博客 269

JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]

类的继承Java只支持单继承,不允许多重继承 - 一个子类只能有一个父类 - 一个父类可以派生出多个子类 子类继承了父类,就继承了父类的方法和属性。 在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。 因而,子类通常比父类的功能更多。 在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。 关于继承的规则: 子类

5318

Java基础加强_Eclipse、枚举、反射、注解、泛型、类加载器、动态代理

Eclipse MyEclipse是eclipse的一个插件,使得eclipse可以开发JavaEE项目 javaw.exe是启动java的图形界面所用的虚拟机 Java EE Java Enterprise IDE Integrated Development Environment 工程管理与快捷键设置 设置整个工作间编译器版本和运行时环境的版本 window-->Prefe

技术加工厂 2894

黑马程序员_java_基础加强_静态导入_反射_枚举_注解_内省_泛型

黑马程序员_java_基础加强_静态导入_反射_枚举_注解_内省_泛型_代理 ------- android培训、java培训、期待与您交流! ---------- JDK1.5的新特性。 一、StaticImport 静态导入:导入一个类的静态方法。import static … 二、可变参数 特点:1、只能出现在参数列表的最后面 2、调用可变参数方法时,编译器为可变参数隐

翠月风 812

Java基础知识点总结

2. 例如byte类型是1byte也就是8位,可以表示的数字是-128到127,因为还有一个0,加起来一共是256,也就是2的八次方。 32位和64位机器的int是4个字节也就是32位,char是1个字节就是8位,float是4个字节,double是8个字节,long是8个字节。 3. 基本数据类型的包装类只在数字范围-128到127中用到常量池,会自动拆箱装箱,其余数字范围的包装类则会新建实例。 String及包装类 ========== 1. String类型是final类型,在堆中分.

m0_63102527的博客 93

黑马程序员_java基础加强_静态导入_反射_枚举_注解_内省_泛型_代理

------- http://www.itheima.com" target="blank">android培训、http://www.itheima.com" target="blank">java培训、期待与您交流! ---------- JDK1.5的新特性。 一、StaticImport    静态导入:导入一个类的静态方法。import static … 二、可变参

u013508824的专栏 830

一篇文章带你速度过完Java基础

BIO: 来到厨房,开始烧水NIO,并坐在水壶面前一直等待水烧开。NIO: 来到厨房,开AIO烧水,但不坐在水壶面前一直等,而去做其他事,然后每隔几分钟到厨房看一下有没有烧开。AIO: 来到厨房,开始烧水,不一直等待水烧开,而是坐在水壶上面装个开关,水烧开之后它会通知我们。日常开发中新建 Java 类,比较常见的有 class、interface 等,而注解同样也属于一种类,只不过它的修饰符是 ‘@interface’。

qq_35895490的博客 1960

java核心技术总结

***************** java基础 ***************** 一、java 中的局部变量、实例变量和类变量 二、java中的基本类型和引用类型 三、java中的位操作符 四、关于 java 的方法 1、方法的重载和重写(方法签名:方法名和参数列表) 2、方法的可变参(int … args) (1)基本特点 底层就是用数组来实现的; 在方法内部可变参可以直接当成数组进...

stanwuc的博客 4428

JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程.]

类的继承 Java只支持单继承,不允许多重继承  - 一个子类只能有一个父类  - 一个父类可以派生出多个子类    子类继承了父类,就继承了父类的方法和属性。  在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。  因而,子类通常比父类的功能更多。  在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。

追随内心 610
上一篇: 学生信息系统(用些基本知识实现一点小功能,不涉及数据库)
下一篇: Java基础(异常)
平平无奇的编码小天才
博客等级 码龄6年 15粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值