Java基本知识进阶

时间:2022-05-15 13:46:57

1.static  2.代码块  3.继承  4.抽象类  5.接口  6.多态  7.  8.权限修饰符  9.内部类  10.字节码  11.包装类  12.装箱&拆箱  13.正则表达式  14.异常  15.反射  16.JavaBean  

点击一级标题返回顶部


1.static

1.1.静态可以修饰那些?

  成员变量、成员方法

1.2.静态修饰成员变量的特点?

  被所有对象共享;可以使用类名调用;在创建对象之前加载到内存空间

1.3.静态的注意事项:

  A.静态方法的访问范围?

    可以访问静态成员变量、静态成员方法

    不可以访问非静态成员变量、不可以访问非静态成员方法

  B.非静态的方法可以访问哪些?

    可以访问静态成员变量、静态成员方法

    可以访问非静态成员变量、非静态成员方法

  C.静态方法中可不可以使用this和super?

    不可以

    静态方法在类加载时就开始使用,这时还没有对象

1.4.静态的优缺点

  记录对象共享的属性,并且单独存储。节省内存。缺点:访问局限性

2.代码块

  常见的代码块:局部代码块、构造代码块、静态代码块

  构造代码块的作用:提取构造方法中的共性,每次创建对象时都会执行。在构造方法执行前运行。

  静态代码块的作用:初始化类、加载驱动。随着类的加载而加载。

  局部代码块的作用:存在于方法中,控制变量的生命周期

3.继承

  多个类,有共同的成员变量、成员方法,抽取到另外一个类中。让这多个类去继承这个类。

  单一继承,一个类只可以继承一个父类;
  允许多层继承,一个类可以继承一个父类,也可以作为父类被一个子类继承。

3.1.继承时的特点

  子类只能获取父类的非私有成员变量;

  子类中使用同名变量时,遵循就近原则。

3.1.继承时成员方法的特点

  子类重写了父类方法时,调用的是自己的方法;没有重写时,直接使用父类继承而来的方法。

3.2.方法的重写

  方法重写发生在子类继承父类时,两个使用相同的方法声明。重写后,子类方法覆盖父类继承来的方法。

方法重写的应用场景:

  父类的方法不能满足子类的使用。使用super关键字,可以保有父类方法的功能。

方法重写的主意事项:

  不能重写父类的私有方法;

  修饰符权限须大于、等于父类修饰符权限。

3.3.继承时构造方法执行顺序

  在有子父类继承关系的子类对象实例化时,调用子类的构造方法。如果子类调用的构造方法,第一行代码没有调用父类构造方法,则会默认调用父类的无参构造方法。

  可以使用super()在子类构造中,显示调用父类构造方法。(必须出现在子类构造的第一行,否则出错)

  如果在子类构造的第一行调用了子类的其他构造,那么这个构造就不去调用父类的默认构造。倘若子类中循环调用了子类的构造,则报错。

  当子类构造方法 显示、隐式 调用了父类的无参构造,而父类中不存在 无参构造,则报错。(父类未定义无参构造方法)

  如果子类没有调用父类的无参构造方法,就可以显示调用父类的有参构造方法。使用 super(参数列表)

  不管怎么调,肯定要调用父类的构造,否则就报错。(除非,放弃继承)不仅仅是要调用父类构造,而且还要先执行父类的构造。

class F{

//    public F(){
//        System.out.println("f, no paras");
//    }
//
    public F(int f){
        System.out.println("f, have para");
    }
}

class Z extends F {

    public Z(){
//        super(); //默认调用父类无参
        this(3);  //调用
        System.out.println("z, no para");
    }

    public Z(int z){
        super(z);  //调用父类有参
        System.out.println("z, hava pava");
    }
}

实例:扩展父类功能

public class PBDemo1 extends Pdemo1{
    /*
     * 构造方法     增加功能,实现批量执行
     */
    public PBDemo1(String[] sql) throws SQLException {
        super(sql[0]); //调用父类构造
        for (int i = 1; i<sql.length; i++) {
            pstmt.addBatch(sql[i]);
        }
    }
    public PBDemo1(String[] sql, String url) throws SQLException {
        this(sql); //调用
        setUrl(url); //调用父类方法
    }
}

3.4.this & super

  this,当前对象的应用。super,子类对象的父类引用。(是 “父类引用”,不是 “父类对象引用”)

  this,调用子类的成员变量、成员方法、构造方法(须出现在构造方法的第一行,否则报错)。

  super,调用子类的父类成员变量、成员方法、构造方法(同上)。

  当this调用的成员没有在子类中定义时,引用的从父类继承来的。要是不能从父类继承得到,就可能报错。

3.5.继承的优缺点

  优点,提供代码的复用性,易于维护。

  缺点,代码的耦合性搞了,

3.5.匿名对象

  没有变量名引用的变量。

(new Student()).show();

  应用场景:当方法只调用一次的时候可以使用匿名对象

3.6.final

  用来修饰 类、成员方法、成员变量。final修饰后的类,不能被继承;修饰后的成员变量,不能不能修改值(可以一次性赋值,或者在构造方法中赋值);修饰的成员方法,不能被子类重写。

  final修饰的成员变量,被称为“自定义常量”。

4.抽象类

4.1.什么是抽象类

  使用关键字 abstract,用于修饰方法和类。修饰后的方法就是“抽象方法”,抽象方法没有方法体。修饰后的类,叫“抽象类”。

  有抽象方法的类,必须是抽象类;抽象类可以不包含抽象方法。抽象类,不能实例化;使用抽象类,必须在子类中实现父类的抽象方法。

4.2.抽象类的特点

  不能实例化,需要关键字 abstract 修饰,可以在抽象类中包含非抽象方法。抽象类的子类,必须实现抽象类的抽象方法,要么就必须也是抽象类。

4.3.抽象类的成员特点

  可以存在成员变量,可以是常量。可以有抽象方法、非抽象方法。可以有构造函数。

注意:关键字 abstract 不能跟 final、static、private 一起出现修饰成员、类。

4.4.抽象的思想

  父类不能具体某些方法内容时,使用到抽象方法;仅仅通过抽象方法来设定规则、规范。

5.接口

接口的成员特点:

  • 只能有抽象方法(默认有 abstract 修饰符)
  • 只能有常量
  • 默认用 public abstract 修饰方法
  • 默认用 public static final 修饰常量

注意:

  • 接口不能创建对象(不能实例化)
  • 类与接口是 实现关系。一个类实现一个接口,必须实现其所有方法。
  • 接口中的抽象方法,只能用 public、abstract 修饰。

定义格式:

 interface Animal {
     public static final int n = 15;
     public abstract void jump();
 }

类和接口之间的关系:

  • 类与类:继承关系,单一继承,多层继承
  • 类与接口:实现关系,多实现
  • 接口与接口:继承关系,多继承

接口的思想:

接口的优点:

  • 打破继承的局限性
  • 对外提供接口
  • 降低了程序的耦合性

接口和抽象类的区别:

  • 接口比抽象类更抽象
  • 成员变量:
    • 抽象类可以有成员变量,也可以有常量
    • 接口只能有常量
  • 成员方法:
    • 抽象类可以有抽象方法,也可以有非抽象方法
    • 接口只能有抽象方法(还有默认修饰符)
  • 构造方法:
    • 抽象类有构造方法
    • 接口没有构造方法

接口和抽象类的共性:

  • 不能被实例化
  • 都是不断抽取共性后的一些规则

6.多态

多态的前提:

  • 子父类的继承关系
  • 方法的重写
  • 父类引用指向子类对象

多态的成员特点:

  • 成员变量 -> 编译时看的是 左边,运行时看的是 左边;成员变量没有重写这个事情;
  • 成员方法 -> 编译时看的是 左边,运行时看的是 右边
  • 静态方法 -> 编译时看的是 左边,运行时看的是 左边

多态的优点:

  • 提高了代码的可扩展性
  • 提高了代码的可维护性

多态的缺点:

  • 无法访问子类特有成员

♣接口化程序编写。


  定义接口

 public abstract interface USB {
     public abstract void open();
     public abstract void read();
     public abstract void close();
 }

  扩展接口特性

 public interface USB_IO extends USB {
     public abstract void write();
 }

  定义类实现接口

 public class USB_mouse implements USB {

     @Override
     public void open() {
         System.out.println("鼠标加电");
     }

     @Override
     public void read() {
         System.out.println("获取鼠标指令");
     }

     @Override
     public void close() {
         System.out.println("鼠标断电");
     }

 }

  定义类实现接口

 public class USB_Printer implements USB_IO {

     @Override
     public void open() {
         System.out.println("打开打印机");
     }

     @Override
     public void read() {
         System.out.println("获取打印机当前状态");
     }

     @Override
     public void write() {
         System.out.println("打印文件");
     }

     @Override
     public void close() {
         System.out.println("关闭打印机");
     }
 }

  定义计算机类

 public class Computer {
     public void useUSB(USB usb){
         usb.open();
         usb.read();
         usb.close();
     }
 }
 public class Computer_IO extends Computer {

     public void useUSB(USB_IO usb){
         usb.write();
         super.useUSB(usb);
     }
 }

  测试类

 public class Test01 {
     public static void main(String[] args) {
         Computer_IO mc = new Computer_IO();
         USB_mouse mouse = new USB_mouse();
         USB_Printer hp = new USB_Printer();

         mc.useUSB(mouse);
         System.out.println();
         mc.useUSB(hp);

     }
 }

7.

包的特点:

  • 可以有多层
  • 不同包下可以有同名文件
  • 包的声明必须是文件的第一行

包之间的访问:

  • 相同包
    • 类之间可以直接互相访问
  • 不同包
    • 不能直接访问
    • 需要导包,import 包名.类名;
    • 使用类的全名(包名.类名)

8.权限修饰符

权限修饰符
  当前类 当前包  不同包
子类定义
public  √  √  √  √
protected  √  √  ×  √
default  √  √  ×  ×
private  √  ×  ×  ×
  • default & protected

    在继承关系中,看看区别。在子类定义时看以访问到 protected (public当然也可以)。

 import day04_Task02.QuanXianClass; // 导入需要继承的类

 public class SonClass extends QuanXianClass {
     public void show(){
         super.protectedShow();

         protectedShow(); // 只能在子类访问该方法
     }
 }

    重写都不行,一样会报错。

 @Override
 void defaultShow(){ // 报错
     System.out.println("default");
 }

9.内部类

  内部类,可以理解为“类的内部类”。内部类出现在了一个类之中,在类中不同位置又有不同的叫法。内部类就像类的一个方法一样的存在,于是修饰符就跟方法一样。方法跟类比较,方法多了一个修饰符 static,那么这个内部类就比普通类也多了这么一个修饰符。这就是成员内部类的特性。而局部内部类就像一个局部变量一样存在着,更多的考虑的是有效性范围。

  • 成员内部类:像是类中的一个方法一样
  • 局部内部类:出现类的方法中的一个类
  • 匿名内部类:没有名称的内部类,也是出现在方法中;是一个局部内部类的对象

9.1.成员内部类

定义一个成员内部类(代码中包含了内部类的调用)

 public class OuterClass {
     public static void main(String[] args) {
         new OuterClass().visitInnerClass();
     }

     public void visitInnerClass() {
         InnerClass ic = new InnerClass(); // 第一种方式访问内部类
         ic.show();
     }

     public class InnerClass {

         public void show() {
             System.out.println("This is outputed by inner class's method.");
         }
     }
 }

内部类的外部访问(算作内部类的第二种调用方式)

 public class Test01 {
     public static void main(String[] args) {
         InnerClass ic = new OuterClass().new InnerClass();

     }
 }

内部类使用外部类的成员变量(内部类的使用)

 public class Task01_InnerUseVar {
     String name = "Outer var";

     public class Inner {
         String name = "Inner var";

         public void showName(){
             String name = "Inner showName var";

             System.out.println(name);
             System.out.println(this.name);
             System.out.println(Task01_InnerUseVar.this.name);
         }
     }

     public static void main(String[] args) {
         Inner ic = new Task01_InnerUseVar().new Inner();

         ic.showName();
     }
 }

内部类的静态调用

 public class OutClass {

     public static void main(String[] args) {
         OutClass.InnerClass.showInnerMethod();
     }

     public static class InnerClass{
         public static void showInnerMethod(){
             System.out.println("Inner method");
         }
     }
 }

直接使用,如同静态方法一样

OutClass.InnerClass.showInnerMethod();

<< 内部类的外部访问(算作内部类的第二种调用方式) >>

去掉类的修饰符 static,和内部类的方法修饰符 static,后调用内部类的非静态方法

OutClass2.InnerClass oic = new OutClass2().new InnerClass();
oic.showInnerMethod();

9.2.局部内部类

定义局部内部类、调用之

 class Outer {    

     public void showOuterMethod(){
         // 局部内部类,出现在成员方法中
         class LocalInnerClass {
             public void showLocalInnerClassMethod(){
                 System.out.println("showLocalInnerClassMethod");
             }
         }

         LocalInnerClass lic = new LocalInnerClass();
         lic.showLocalInnerClassMethod();
     }
 }

9.3.匿名内部类

  • 可以看作一个没有名字的局部内部类
  • 定义在方法中
  • 必须在定义匿名内部类的时候,同时创建它的对象
  • 创建格式:创建类,是“类名/接口名”的“子类、或者是实现类”的对象。
    new 类名/接口名 (){
    
    };

匿名内部类是局部内部类的衍化,实现接口创建对象

 class Outer {

     void showTime() {

         // 使用接口实现匿名内部类的使用
         new USB_i() { // 使用 接口 USB_i 创建对象

             @Override
             public void showUSB() {
                 // TODO Auto-generated method stub
                 System.err.println("USB,interface implements");
             }
         }.showUSB(); // 创建对象时,直接调用实现的接口方法

         // 匿名内部类的可以赋值给一个变量
         USB_i ui = new USB_i() {

             @Override
             public void showUSB() {
                 // TODO Auto-generated method stub
                 System.out.println("USB, interface implements as a variable.");
             }
         };

         ui.showUSB(); // 使用变量调用局部内部类的方法
     }

 }

 interface USB_i {
     public abstract void showUSB();
 }

 abstract class USB_ac {
     public abstract void showUSB();
 }

 class USB_c {

     public void showUSB() {
         System.out.println("USB, class implements");
     }
 }

除了接口,继承类创建对象、继承抽象类实例化 创建匿名内部类

 void showTime2() {

         // 使用接口实现匿名内部类的使用
         new USB_c().showUSB(); // 创建对象时,直接调用实现的接口方法

         // 匿名内部类的可以赋值给一个变量
         USB_c ui = new USB_c();

         ui.showUSB(); // 使用变量调用局部内部类的方法
     }

     void showTime3() {

         // 使用接口实现匿名内部类的使用
         new USB_ac() { // 使用 接口 USB_i 创建对象

             @Override
             public void showUSB() {
                 // TODO Auto-generated method stub
                 System.err.println("USB,abstract class implements");
             }
         }.showUSB(); // 创建对象时,直接调用实现的接口方法

         // 匿名内部类的可以赋值给一个变量
         USB_ac ui = new USB_ac() {

             @Override
             public void showUSB() {
                 // TODO Auto-generated method stub
                 System.out.println("USB, abstract class implements as a variable.");
             }
         };

         ui.showUSB(); // 使用变量调用局部内部类的方法
     }
  • 匿名内部类的使用场景:
    • 匿名类的使用,在编译后不会创建单独的 class 文件。基于这个属性,或者说在一个项目中,有一个类只使用一次,完全没有必要为其生成一个文件。
    • 程序执行时,为一小段代码需要多一次文件读取,在性能角度很不值得。

10.字节码

  • 字节码对象,属于整个类。包括类、以及类的对象共有。
  • 获取字节码对象的方法:
    • 对象,对象名.getClass()
    • 类名,类名.class
    • Class类的静态方法,Class.forName("类名字符串")
  • 字节码对象的数据类型?Class<?>
  • Class 类的实例表示正在运行的 Java应用程序中的类和接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。

11.包装类

  • 什么是包装类?包装了基本数据类型的类
  • 意义?基本数据类型只提供了一些简单的操作和运输。包装类,提供了更多复杂的方法和一些变量。(方便使用)
  • 4类8种:Byte、Short、Integer、Long、Character、Float、Double、Boolean
 System.out.println(Integer.MAX_VALUE); // 20亿 十位
 System.out.println(Integer.MIN_VALUE); // 表示10位
 System.out.println(Integer.SIZE); // 占用32位存储空间  

 System.out.println(Byte.MAX_VALUE);
 System.out.println(Byte.MIN_VALUE); // -128 ~ 12
 System.out.println(Byte.SIZE); // 占用8位存储空间      

 System.out.println(Short.MAX_VALUE);
 System.out.println(Short.MIN_VALUE); // -32768 ~
 System.out.println(Short.SIZE); // 占用16位存储空间    

 System.out.println(Long.MAX_VALUE); // 20位
 System.out.println(Long.MIN_VALUE);
 System.out.println(Long.SIZE); // 占用64位存储空间     

 System.out.println(Float.MAX_VALUE);
 System.out.println(Float.MIN_VALUE); // 40位
 System.out.println(Float.SIZE); // 占用32位存储空间    

 System.out.println(Double.MAX_VALUE);
 System.out.println(Double.MIN_VALUE); // 300位
 System.out.println(Double.SIZE); // 占用64位存储空间   

 System.out.println(Character.MAX_VALUE); // ???
 System.out.println(Character.MIN_VALUE);
 System.out.println(Character.SIZE); // 占用16位存储空间

11.1.Integer

  • 构造方法:没有无参构造;创建该包装类必须要有参数
包装类 Integer

构造方法 格式

说明

public Integer(int value) 由整数构造
public Integer(String s) 由整数的字符串格式构造
  • 字段:全静态
包装类 Integer

字段

说明

public static final int MAX_VALUE int类型表示的最小值;-231
public static final int MIN_VALUE int类型表示的最大值;232 - 1
public static final int SIZE 比特位数
public static final Class<Integer> TYPE  
System.out.println(Integer.MAX_VALUE); // 范围的最小值:2147483647
System.out.println(Integer.MIN_VALUE); // 范围的最大值:-2147483648
System.out.println(Integer.SIZE); // 占用内存的位数(bit):32
System.out.println(Integer.TYPE); // :int
包装类 Integer
 

常用方法 格式

参数

说明

建议 public static Integer valudeOf(int i)   优先使用该方法,创建实例
转换 public byte byteValue()   以 byte 类型返回
  public short shortValue()    
  public static Integer valueOf(String s) s 可以是整数字符串、或者单个字符 返回 s 表示的整数

11.2.Boolean

  • 构建 布尔 类变量
Boolean boo = Boolean.getBoolean("true");

12.装箱&拆箱

  • 装箱,Jvm 把基本数据类型值转换成包装类对象

整数包装成 Integer 类型

Integer i = 10; // 把一个基本类型赋值给引用类型
// Integer i = Integer.valueOf(10);
  • 拆箱,Jvm 把包装类对象转换成基本数据类型的值
int i = new Integer(10); // 也不会报错,自动拆箱
// int i = new Integer(10).intValue();
Integer i = 10;
Integer j = 12;
Integer sum = i + j;

13.正则表达式

  • 匹配语法:
String regex = ".*e.*";
String str = "hello";

// SOP 1
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
boolean flag = m.matches();
System.out.println(flag);

// SOP 2
System.out.println(Pattern.matches(regex, str));
  • 匹配规则:匹配模式表示的字符数量,须匹配到匹配对象的字符数量;一个字母 e,是匹配不到 hello 的。
  • 元字符
Java 的正则表达式 元字符
 

元字符 表达式

说明

 
字符  a  字符 a  
   \\  反斜线  
   \r  回车  
字符类  [abc]  a、b、c  
   [a-z]  小写字母  
预定义  .  任意字符  
   \d  数字  
   \D  非数字  
   \s  空白字符  
   \S  非空白字符  
   \w  单词字符 单个的 大小写字母、数字、下划线
   \W  非单词字符  
边界  ^  行首  
   $  行尾  
次数  a?  零次或一次  
   a*  零次或多次  
   a+  一次或多次  
   a{n}  n次  
   a{n,}  至少n次  
   a{n, m}  至少n次、至多m次  

14.异常

14.1.抛出异常

  • 抛出“编译时异常”,创建“Exception类”对象,throw it
public static void fun(int n) throws Exception {
    if (n >= 4) {
        throw new Exception("大四异常");
    }
}
  • 抛出“运行时异常”,创建“RuntimeException类”对象,throw it
public static void fun(String s) {
    if (s == null) {
        throw new RuntimeException("空字符串异常");
    }

    if (s.isEmpty()) {
        throw new RuntimeException("字符串零长度异常");
    }

    if (s.equals("argor")) {
        throw new RuntimeException("argor异常");
    }
}

14.2.自定义异常类

  • 编译时异常,继承“Exception类”对象,重写构造方法
public class Luck98 extends Exception {

    public Luck98() {
        super();
    }

    public Luck98(String message) {
        super(message);
    }

}
  • 运行时异常,继承“RuntimeException类”对象,重写构造方法
public class CongratulationsOnMakingMoney extends RuntimeException {

    public CongratulationsOnMakingMoney() {
        super();
    }

    public CongratulationsOnMakingMoney(String message) {
        super(message);
    }

}

14.3.抛出自定义异常

public static void main(String[] args) {
    try {
        fun(3);
    } catch (Luck98 e) {
        e.printStackTrace();
    }
}

public static void fun(int n) throws Luck98{
    n = 4;
    throw new Luck98("大四异常");
}

15.反射

反射理论:

作用:程序运行时,动态创建对象,动态调用方法,动态获取属性

	反射的前题:
		要有类对象(字节码对象)
		获取方法:Class.forName("类名");

反射 -> 获取构造方法
	Constructor<?>[] getConstructs()		返回所有的 public 构造方法对象数组
	Constructor<?> getConstruct(Class<?>... parameterTypes)		返回构造方法对象(参数是字节码对象)
		不给参数时,创建一个无参构造方法对象
			Constructor[] c1 = clazz.getConstructs();
			Constructor c1 = clazz.getConstruct();
		给定参数时,可以获取一个指定参数列表的对象
			Constructor c2 = clazz.getConstruct(String.class, int.class);
			Constructor[] c3 = clazz.getDeclaredConstructs();

	构造方法对象的方法: newInstance(...) 创建一个实例
							c1.newInstance();
							c1.newInstance("lisi", 30);

	总结:字节码对象 -> 构造方法 -> 创建对象
	扩展:字节码对象 -> 创建对象(只能使用无参构造)

反射 -> 获取成员变量
	获取成员变量对象
		Field[] fs = clazz.getFields();		public 成员变量
		Field[] fs2 = clazz.getDeclaredsFields();	所有成员变量
		Field f1 = clazz.getField("age");
		Field f1 = clazz.getDeclaredField("age");

	操作成员变量的值
		Object objField = f1.get(obj);
		f1.set(obj, newValue);

反射 -> 获取私有成员变量
	Class clazz = Class.forName("...");
	Object obj = clazz.newInstance();
	Field f = clazz.getDeclaredField("name");
	f.setAccessible(true);

反射 -> 获取成员方法
	Class clazz = Class.forName("...");
	Object obj = clazz.newInstance();

	获取方法对象
		Method[] ms = clazz.getMethods();

		获取无参无返回方法
			Method m1 = clazz.getMethod("displayName");
			m1.invoke(obj);
		获取有参无返回方法
			Method m2 = clazz.getMethod("setName", String.class);
			m2.invoke(obj, "huazi");
		获取无参有返回方法
			Method m3 = clazz.getMethod("toString");
			Object o = m3.invoke(obj);

字节码对象

  Class 没有公共构造方法。Class 对象是在加载类时自动构造的。

Class 常用方法
 

方法格式

说明

字节码 static Classe<?> forName(String name) 获取字节码对象,字符串是一个类的全名称
构造方法 Constructor<T> getConstructor(Class<?>... paraType)  
字段  Field getDeclareField(String name) 获取所有声明过的字段
Field getField(String name) 获取可见字段
Field[] getFields() 获取全部字段,返回一个对象数组
方法
  
Method getMethod(String name, Class<?>... parameterType) 获取可见方法
Method[] getMethods()  
Method getDeclaredMethod(String name, Class<?>... ParameterTypes ) 参数 name 表示方法名,ParameterTypes 代表参数列表……
  • 功能:获取构造、获取成员变量、获取成员方法
  • 场景:以类为变量的应用需求(不是以对象为变量)

示例:获取构造方法

Class clazz = Class.forName("day13.Student"); // 获取字节码对象
Constructor c = clazz.getConstructor(); // 通过字节码对象获取构造方法,赋值给构造方法变量
Object obj = c.newInstance(); // 调用构造方法创建对象
System.out.println(obj); // 可以直接输出重写了 toString 方法的类对象

Constructor c2 = clazz.getConstructor(String.class, int.class); // 获取带参构造方法
Object obj2 = c2.newInstance("wangwu", 18) // 创建对象

Object obj3 = clazz.newInstance(); // 使用字节码对象的方法,也可以直接获取无参构造方法

示例:获取成员变量

Object obj = clazz.newInstance(); // 使用字节码对象创建对象
Field fs = clazz.getDeclaredField("name"); // 使用字节码对象获取字段
fs.setAccessible(true); // 设置字段可访问
fs.set(obj, "小明"); // 修改字段值

示例:获取成员字段,并直接输出字段

Class clazz = Class.forName("day13.Student");
Object obj = clazz.newInstance();
Field f1 = clazz.getDeclaredField("age");
f1.setAccessible(true);
f1.set(obj, 35);
System.out.println(f1.get(obj));

示例:获取成员方法

Object obj = clazz.newInstance(); // 获取对象
Method fun = clazz.getMethod("getAge"); // 无参方法
Object field1 = fun.invoke(obj); // 执行方法,获取方法的返回值

Method setName = clazz.getMethod("setName", String.class);  // 有参方法的获取
setName.invoke(stu, "赵六"); // 执行方法,设定字段值

Exercise:

//反射应用模板
Class clazz = Class.forName("day13.Student"); // 获取字节码对象
// 通过字节码对象获取对象
Object obj = clazz.newInstance();

// 设置字段值
Field name = clazz.getDeclaredField("name");
name.setAccessible(true); // 私有字段
Field age = clazz.getDeclaredField("age");
age.setAccessible(true); // 私有字段
name.set(obj, "小龙");
age.set(obj, 33);
System.out.println(obj);
// 单独输出字段
System.out.println(age.get(obj));

// 通过字节码对象,获取方法
Method f1 = clazz.getDeclaredMethod("show"); // 调用无参
f1.setAccessible(true); // 私有方法
f1.invoke(obj);

Method f2 = clazz.getDeclaredMethod("show", String.class); // 调用有参
f2.setAccessible(true); // 私有方法
f2.invoke(obj, "Times");

16.JavaBean

  • 用于封装数据:
    • 类使用 public 修饰
    • 提供 private 修饰的成员变量
    • 为成员变量提供公共 get/set 访问方法
    • 提供 public 无参构造方法
    • 实现序列接口(序列化,必要时须写入文件)

实例:JavaBean 实现类

import java.io.Serializable;

public class Student implements Serializable {

    private static final long serialVersionUID = -6451757171854168084L;
    private String name;
    private int age;
    private int salary;

    public Student() {
        super();
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", salary=" + salary + "]";
    }
}
  • 三个常用的重要方法

方法格式

说明

static void setProperty(Object bean, String name, Object value) 为 JavaBean 对象的成员变量 name 赋值
static String getProperty(Object bean, String name)  
static void populate(Object bean, Map properties)  

示例:为 JavaBean 对象赋值

Student stu1 = new Student();
BeanUtils.setProperty(stu1, "name", "阿龙");
BeanUtils.setProperty(stu1, "age", 33);
BeanUtils.setProperty(stu1, "salary", 1333);

示例: 从 JavaBean 对象获取值

String name = BeanUtils.getProperty(stu1, "name");
String age = BeanUtils.getProperty(stu1, "age");
String salary = BeanUtils.getProperty(stu1, "salary");

示例: 使用 方法 populate 为 JavaBean 赋值

Student stu1 = new Student();
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "阿龙");
map.put("age", 33);
map.put("salary", 1333);
BeanUtils.populate(stu1, map);

lombok

  1. 配置
    -javaagent:lombok-1.16.18.jar
    -Xbootclasspath/a:lombok-1.16.18.jar
  2. 示例代码
    package pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Employee {
        private Integer id;
        private String lastName;
        private String email;
        private Department deptId;
    }
  3. 示例效果 .Java基本知识进阶