一、类中的成分:代码块
代码块是类的五大成分之一:成员变量,构造器,方法,代码块,内部类
1.1静态代码块
格式: static { }
特点:静态代码块由类本身持有,由于类只会加载一次,所以静态代码块也只会被执行一次
并且,静态代码块是优先执行的。比如下面代码,main方法在后面执行
作用:完成类的初始化,对静态变量进行初始化赋值
java
//认识静态代码块
public class CodeDemo1 {
//静态代码块,由static修饰,属于类,与类一起优先加载,执行一次
public static String name;
//作用,对类的资源初始化
static{
System.out.println("静态代码执行力");
name = "张三";
}
public static void main(String[] args) {
System.out.println("main 方法执行了");
}
}
1.2实例代码块(构造代码块)
格式:{ }
特点:属于对象,每次创建对象时,执行实例代码块,并在构造器前执行
二、类中的成分:内部类
如果一个类定义在另一个类的内部,就称为内部类
场景:当一个类的内部有另一个完整的事务,且这个事务没有必要单独设计,就把他设计成内部类
2.1成员内部类
成员内部类就是类中的一个普通成员,类似之前学过的成员方法,成员变量。
特点:属于外部类的对象持有,因此不加static修饰!!
创建方法:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
java
public class outer {
//成员内部类,属于外部类对象,不能加static
//创建方法:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
public class inner {
public static void main(String[] args) {
}
/*内部类的特点:
1.可以直接访问外部类的静态成员(静态变量,静态方法)
2.可以直接访问外部类的实例成员
3.成员内部类的实例方法,可以直接拿到当前寄生的外部类对象: 外部类名.this
*/
}
}
java
public class demo1 {
public static void main(String[] args) {
outer.inner oi = new outer().new inner();
}
}
2.2静态内部类
由static修饰的内部类,属于外部类本身持有,由于外部类只会加载一次,它也只加载一次
语法: 外部类名.内部类名 对象名 = new 外部类.内部类();
java
//认识静态内部类
public class demo {
public static void main(String[] args) {
Outer.Inner oi = new Outer.Inner(); //格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
//静态类可以访问外部类的静态成员吗? 可以
//静态内部类中是否可以直接访问外部类的实例成员? 不可以!
System.out.println(Outer.SchoolName);
System.out.println(age); //报错
}
}
2.3局部内部类(了解)
定义在方法,构造器里的类,没啥用
三、匿名内部类(重要)
3.1认识匿名内部类
1.匿名内部类,是一种特殊的局部内部类
2.所谓匿名,是因为不需要为这个类声明名字,它默认有个隐藏的名字
格式:虽然没有class关键字,但它就是一个类!!
java
new 类或接口名(参数值){
类体(一般是方法重写);
};这个分号不能忘掉!!
特点:匿名内部类,本质上就是一个子类,并且会立即创建出一个子类对象
java
//认识匿名内部类及基础作用
public class test {
public static void main(String[] args) {
/*
传统写法如下,定义一个新的类,继承animal,调用cat的cry方法。
Animal a = new cat();
a.cry();
*/
//匿名内部类的写法:直接new animal,但是animal是抽象类,不能直接new
//因此使用匿名内部类来new,new完之后需要立即重写cry方法
Animal b = new Animal() {
@Override
public void cry() {
System.out.println("猫 喵喵叫");
}
}; // new后面这一坨,就是匿名内部类,它就是animal的子类 ,注意这里需要分号
b.cry();
}
}
/*
class cat extends Animal{
@Override
public void cry(){
System.out.println("cat 喵喵");
}
}
*/
匿名内部类的作用:更方便的创建子类对象
3.2匿名内部类常见使用形式
通常作为一个对象参数传给方法。
需求:学生,老师参加游泳比赛
java
//认识匿名内部类的使用形式:可作为对象参数传输给方法使用
//需求:学生,老师参加游泳比赛
public class test2 {
static swim teacher = new swim(){
@Override
public void swimming(){
System.out.println("老师正在自由泳");
}
};
public static void main(String[] args) {
Start(teacher);
Start(new swim() {
@Override
public void swimming() {
System.out.println("学生正在蛙泳");
}
}); //内部类对象直接作为参数写进去,跟上面是等价的
}
//设计一个方法,可以接收老师,学生参加比赛
public static void Start(swim s) {
System.out.println("比赛开始");
s.swimming();
System.out.println("比赛结束");
}
}
interface swim {
public void swimming();//游泳方法
}
使用场景:
调用别人写好的方法实现需求时,传入一个匿名内部类对象给其使用。
例子:使用Comparator接口的匿名内部类对数组进行排序
java
//完成数组的排序,理解匿名内部类在这里的用法
public class test3 {
public static void main(String[] args) {
Student[] Students = new Student[4];
Students[0] = new Student("张三",18,175.4,'男');
Students[1] = new Student("李四",20,169.5,'女');
Students[2] = new Student("王五",16,183.0,'男');
Students[3] = new Student("张麻子",35,171.3,'男');
//需求,对数组按年龄大小排序
//public static <T> void sort(T[] a, Comparator<? super T> c)
//参数1:需要排序的数组
//参数2:给sort方法声明比较器Comparator对象,指定排序规则
//Comparator是一个接口,我们用匿名内部类来做
//sort 方法会调用匿名内部类的compare方法,对数组中的元素进行比较
Arrays.sort(Students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//指定排序规则
//如果你认为左边对象 大于 右边对象,返回正整数
//如果你认为左边对象 小于 右边对象 , 返回负整数
//相等,返回 0
if(o1.getAge()>o2.getAge()){
return 1;
}else if(o1.getAge()<o2.getAge()){
return -1;
}
return 0;
//上面这一大段也可以写成 return o1.getAge - o2.getAge 按照年龄升序
//return o2.getAge - o1.getAge 按照年龄降序
}
});
for (Student s : Students) {
System.out.println(s);
}
}
}