内部类
- 如果一个类定义在另一个类的内部,这个类就是内部类
成员内部类
package demo0321;
public class Outer {
private int age = 99;
public static String a;
public class Inner{
private int age = 88;
private String name;
public static String User; // JDK16才开始支持定义静态成员的
// 成员内部类可以正常访问外部类的变量
public void test(){
System.out.println(age);
System.out.println(a);
int age = 66;
// 直接age访问的是最近的变量
System.out.println(age);
// this.age访问内部类的相关变量
// this.age在内部类中不存在age的时候,会出现异常
System.out.println(this.age);
// 通过外部类.this可以获取最外部类的变量
System.out.println(Outer.this.age);
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
}
package demo0321;
public class Test {
public static void main(String[] args) {
// 成员内部类创建对象
// 需要先new出外部类,在.new成员内部类
Outer.Inner in = new Outer().new Inner();
in.setName("Hello");
System.out.println(in.getName());
in.test();
}
}
静态内部类
package demo0321;
public class Outer {
private int age;
public static String className;
public static class Inner{
private String name;
public static int a;
public Inner() {
}
public void test(){
System.out.println(className);
// 静态内部类和静态方法一样,可以直接访问类的类变量,不能访问外部类的实例变量
// System.out.println(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
package demo0321;
public class Test {
public static void main(String[] args) {
// 静态内部类创建对象
Outer.Inner in = new Outer.Inner();
in.setName("hello");
System.out.println(in.getName());
in.test();
}
}
匿名内部类
- 就是一种特殊的局部内部类,所谓匿名: 指的是程序员不需要为这个类声明名字
// 匿名内部类的格式
new 类或接口(参数值){
类体(一般是方法重写)
}
2.特点: 匿名内部类本身就是一个子类,并会立即创建出一个子类对象
3.优势和应用场景
1.可以更方便创建出一个子类对象
2.匿名内部类通常作为一个参数传递给方法
package demo0321;
abstract class Animal{
public abstract void cry();
}
class Cat extends Animal{
@Override
public void cry(){
System.out.println("小猫在叫~~");
}
}
public class Test {
public static void main(String[] args) {
// 正常使用该方法
Animal a = new Cat();
a.cry();
// 通过匿名内部类实现
// 把这个匿名内部类编译成一个子类,然后会立即创建一个子类对象出来
Animal dog =new Animal(){
@Override
public void cry(){
System.out.println("小狗在叫");
}
};
dog.cry();
}
}
通过案例进一步理解内部类
package demo0321;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test {
public static void main(String[] args) {
// 扩展,搞清楚内部类在开发中的真实应用场景
// GUI编程
// 1.创建窗口
JFrame win = new JFrame("登录界面");
JPanel panel = new JPanel();
win.add(panel);
JButton btn = new JButton("登录");
panel.add(btn);
// 给按钮绑定单击时间监听器
// 通过匿名内部类可以做到简化代码的作用
// 比如这里我们可以不需要在单独创建出一个ActionListener实现类,而是直接传递
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win, "登录一下");
}
});
win.setSize(400, 400);
win.setLocationRelativeTo(null);
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
win.setVisible(true);
}
}
枚举
1. 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象
2. 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象
3. 枚举类都是最终类,不可以被继承
4. 枚举类中,从第二行开始,可以定义类的其他各种成员
5. 编译器为枚举类新增了几个方法,并且枚举类都是继承: java.long.Enum类的,从enum类也会继承到一些方法
package demo0321;
public enum A {
// 枚举类的第一行必须罗列的是枚举对象的名字
X, Y, Z;
// 后面内容可以编写类的其他内容
private String Classname;
public String getName() {
return Classname;
}
public void setName(String name) {
this.Classname = name;
}
}
package demo0321;
public class Test {
public static void main(String[] args) {
A a = A.X;
System.out.println(a);
// 枚举类一些额外的API
A [] as = A.values(); // 得到枚举的全部对象
System.out.println(as);
A a1 = A.valueOf("Y"); // 获取枚举的单个对象
System.out.println(a1);
System.out.println(a1.name()); // 获取对象的名称
System.out.println(a1.ordinal()); // 获取对象的索引
}
}
抽象枚举
package demo0321;
public enum B {
// 抽象枚举
// 在第一行创建对象的时候,需要重写抽象方法,否则异常
X("张三"){
@Override
public void go() {
System.out.println(getName());
}
}, y("李四"){
@Override
public void go() {
System.out.println(getName());
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
B(String name) {
this.name = name;
}
public abstract void go();
}
package demo0321;
public class Test {
public static void main(String[] args) {
B y = B.y;
y.go();
}
}
枚举的应用场景
- 适合用来进行标志
**案例:**根据用户的输入男女,决定给用户推荐那些信息
1.使用变量进行区分
package demo0321;
// 使用变量时,如果面对大量代码的时候,会严重影响可读性
public class Test {
public static void main(String[] args) {
check(0);
check(1);
check(5);
}
public static void check(int sex){
switch (sex){
case 0:
System.out.println("展示美女");
break;
case 1:
System.out.println("展示帅哥");
break;
default:
System.out.println("美女帅哥五五分展示");
break;
}
}
}
2.使用常量进行区分
package demo0321;
public class A {
public static final int Boy = 0;
public static final int GIRL = 1;
}
package demo0321;
public class Test {
public static void main(String[] args) {
check(A.Boy);
check(A.GIRL);
}
public static void check(int sex){
switch (sex){
case 0:
System.out.println("展示美女");
break;
case 1:
System.out.println("展示帅哥");
break;
default:
System.out.println("美女帅哥五五分展示");
break;
}
}
}
3.使用枚举
package demo0321;
public enum A {
Boy,GIRL;
}
package demo0321;
public class Test {
public static void main(String[] args) {
check(A.Boy);
check(A.GIRL);
}
public static void check(A sex){
switch (sex){
case Boy:
System.out.println("展示美女");
break;
case GIRL:
System.out.println("展示帅哥");
break;
default:
System.out.println("美女帅哥五五分展示");
break;
}
}
}
泛型
1.定义类、接口、方法时,同时声明一个或者多个类型变量(如),称为泛型类、泛型接口、泛型方法,它们统称为泛型
2.作用: 泛型提供了在编译阶段约束所能操作的数据类型,并自动检查的能力!
3.泛型的本质: 把具体的数据类型作为参数传递給类型变量
自定义泛型类
package demo0321;
// 在定义类时,携带<x>,就成为泛型类,x任意,一般使用E
public class A<E>{
public boolean add(E a){
return true;
}
public E get(int index){
return null;
}
}
package demo0321;
public class Test {
public static void main(String[] args) {
A<String> a = new A();
a.add("Java");
// 不是泛型指定的数据类型,使用则异常
// a.add(15);
String name = a.get(5);
// 不是泛型执行的数据类型,会出现异常
// int age = a.get(3);
}
}
自定义泛型接口
package demo0321;
public interface A <X, Y>{
void add(X t, Y z);
}
package demo0321;
public class B implements A<String, String>{
@Override
public void add(String t, String z) {
System.out.println(t);
System.out.println(z);
}
}
package demo0321;
public class Test {
public static void main(String[] args) {
B b = new B();
b.add("hello", "world");
}
}
自定义泛型方法
package demo0321;
public class Test {
public static void main(String[] args) {
// int z = test("java");
String u = test("Java");
}
public static <T> T test(T t){
return t;
}
}
通配符
package demo0321;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
// 可以是任意数据类型的数据
ArrayList<?> arr = new ArrayList<>();
// 必须是B类的子类
ArrayList<? extends B> arr1 = new ArrayList<>();
// 必须是B类的父类或者子类
ArrayList<? super B> arr2 = new ArrayList<>();
}
}
擦除
- 泛型是工作过在编译阶段的,一旦程序编译成class文件,class文件就不存在泛型了,这就是泛型删除
- 泛型不支持基础数据类型.只能支持对象类型(引用数据类型)