20190717(内部类、计时器)
标签: java
**
- #内部类
**
##1.什么是内部类
就是在一个类中又编写了另外一个类
我们将内部类称为 inner ,外部类称为 outer
class A{class B{}}
内部类有很多种,这里讲两种
##2.成员内部类
在类的成员位置,编写的内部类,称之为成员内部类
2.1 成员内部类可以使用全部四种访问修饰符修饰
2.2 成员内部类中的方法是可以访问外部类中的私有成员(属性和方法),inner内部类是outer外部类的一部分
2.3 外部类可以在方法中实例化内部类对象并访问内部类的私有成员
外部类和内部类互相都没有秘密,只是内部类可以直接访问,外部类需要实例化一个内部类对象才可以调用
2.4 当内部类与外部类有重名成员(属性、方法)时,内部类中调用外部类重名成员前需要使用
类名.this.属性名 来调用
2.5 如果在主函数或其他类中需要实例化内部类对象,需要导包(导入包名.外部类.内部类)
实例化对象时要 内部类类名 对象名 = new 外部类类名().new 内部类类名()
Inner inn = new Outer().new Inner();
真心不建议这样写,很沙雕。。。
2.6 所有类(包括内部类)在编译后都会有自己独立的.class文件
代码
public class Outer {
private int n;
public int nn;
//在成员位置编写一个内部类
//这个内部类就是成员内部类
class Inner{
private int m;
public int mm;
public int nn;
public void abc(){
n=20;
//调用重名属性
Outer.this.nn = 40;
}
}
public void cba(){
Inner inner = new Inner();
inner.m = 20;
inner.abc();
}
}
##3.匿名内部类
匿名 内部类就是在内中通过就地实现父类(接口),而编写的一个没有名字的内部类、
3.1 匿名内部类必须通过继承一个父类,或实现一个接口,才能编写
3.2 匿名内部类通常编写在方法中
3.3 匿名内部类也可以使用外部类中的私有成员,并且成员重名时和成员内部类的处理方式一样
3.4 **特别需要注意的:**匿名内部类的对象是向上造型后的,所以只能调用到继承的父类的可访问成员
3.5 修改:匿名内部类的方法中,不能修改该内部类所在方法中局部变量的值(完全不能修改)
3.6 访问:匿名内部类中的方法如果想访问该内部类所在方法中的局部变量,需要保证该局部变量只被赋值一次
(可以访问,但类似于final修饰)
在jdk1.6及其以前,如果需要访问匿名内部类所在方法中的局部变量需要给这个成员变量加final修饰
代码
public class Aoo {
private int n;
public int nn;
public void abc(){
//编写一个匿名内部类,继承Fruit抽象父类
Fruit f = new Fruit(){
//这就是匿名内部类,没名字,但是相当于继承了Fruit类
private int m;
public int mm;
//重写一下抽象父类中的抽象方法
public void eat(){
n = 20;
System.out.println("榴莲掰开吃");
}
};
}
public void cba(){
int i = 20; //局部变量
//i = 250; //再次赋值会对匿名内部类的使用造成影响
Fruit fr = new Fruit(){
public void eat(){
//i = 10; //不能修改所在方法的局部变量
//可以输出,但是如果在方法中再次对这个访问值赋值了也不行
//相当于被final修饰了一样
System.out.println(i);
}
};
}
}
abstract class Fruit {
private int a;
public abstract void eat();
}
- #计时器
##1.什么是计时器
一般用于设定每隔一段时间调用一次某个方法的功能
##2.计时器的目的
例如:每隔1秒,在控制台上输出一个hello
##3.使用计时器的步骤
3.1 步骤1:
实例化一个计时器对象 Timer timer = new Timer();
3.2 步骤2:
使用匿名内部类继承TimerTask类,重写方法,编写每隔一段时间要做的事
TimerTask task = new TimerTask() {public void run() {}}
3.3 步骤3:
使用计时器来设置并周期运行TimerTask
timer.schedule(task,1000,1000);
这个方法的参数都是时间,单位是毫秒,
第一个参数写匿名内部类;第二个参数表示run方法第一次执行,要延时多久;第三个参数表示run方法第一次执行后周期性执行的间隔
3.4 计时器的停止
实例化的计时器对象.cancel();
代码:
import java.util.Timer;
import java.util.TimerTask;
public class TimeDemo {
//如果在这里声明要声明成静态的,因为主函数是静态的只能调用静态属性
//static int i = 1;
public static void main(String[] args) {
//这里是方法中,这里声明的变量,匿名内部类只能访问无法修改,不能i++
//int i = 1;
System.out.println("start:");
//每隔1秒,在控制台上输出一个hello
//1.实例化计时器对象
Timer timer = new Timer();
//2.使用匿名内部类来重写TimerTask的方法
TimerTask task = new TimerTask() {
int i=1; //在匿名内部类内部声明没问题
public void run() {
//这个方法就是会被周期调用的方法
//10秒后停止调用周期输出
if(i==10){
//4.计时器周期调用的关闭
timer.cancel();
}
//没有到10秒就继续输出
System.out.println(i++);
}
};
//3.使用计时器来设置并周期运行TimerTask
//第一个参数写匿名内部类
//这个方法的参数都是时间,单位是毫秒
//第二个参数表示run方法第一次执行,要延时多久
//第三个参数表示run方法第一次执行后周期性执行的间隔
timer.schedule(task,1000,1000);
}
}
##练习:
1.实现从程序开始的第3秒后,每隔500毫秒依次在控制台输出
1
2
3
4