final关键字
Final变量
1. final变量
final关键字可用于声明便令声明,一旦该变量声明,就不可以更改该变量的值。通常由fianl定义的变量为常量
2. final声明变量的语法
①:final关键字修饰的变量,一般都是全部大写字母,以区分和常量的区别
②:final关键字修饰的变量,可以是基本数据类型也可以是引用类型
③:final关键字修饰的变量不可以在其他任何地方赋值,否则会编译期间就会不通过
④:final关键字修饰的变量一般要在定义的时候赋值,否则是默认值,可能不是你需要的。
⑤:final关键字修饰的的对象只能只能恒定的指向一个对象
⑥:一个既被static修饰又被static关键字修饰的变量,占据一段不能改变的存储空间
⑦:一个被定义的final的对象引用只能指向唯一一个对象,不可以将它在指向其他对象,但是一个对象本身的值却可以被改变的。
下面就验证一下7
publicclass FinalTest {
privatestatic Random rand = new Random();//产生随机数,每次为final变量赋值
privatefinalinta=rand.nextInt(10);
privatestaticfinalintb = rand.nextInt(10);
publicstaticvoid main(String[] args) {
//第一次获取final的值
FinalTest test1 = new FinalTest();
System.out.println(test1.a);
System.out.println(test1.b);
//第二次获取final的值
FinalTest test2 = new FinalTest();
System.out.println(test2.a);
System.out.println(test2.b);
}
}
运行结果如下
2
0
8
0
可以看到static final定义的在每次运行的时候都不变,可是final定义的只能是在当次运行之中不变。所以通常真正做到不变,需要用staticfinal修饰
Final方法
关于final方法,我只想说一句,就是final定义的方法是不能被重写的。即将方法定义为final,子类继承父类的时候是不能重写这个方法的。我们都知道权限修饰符private修饰的方法不能被重写,也就是说其实private修饰的方法隐式定义了final
Final类
定义final的类不允许被继承,final类中所有的方法都被隐式的设置为final方法,但是变量可以是final的或者是非final的。比如String就是final修饰的类,是不可以被继承的。
格式如下:
final类名{}
内部类
什么是内部类?
将在类中定义的那个类称为内部类,内部类可以分为成员内部类、局部内部类以及匿名内部类
成员内部类
◆什么是成员内部类
成员内部类,就是在类中定义一个类,并且这个类和成员变量以及成员方法并列,而不是存在于方法中这个就是成员内部类,
◆成员内部类的语法:
public classOutClass{///外部类
private classInnerClass{//内部类
}
}
◆内部类的注意事项:
①:在内部类中可以随便使用外部类的成员变量和成员方法,即使这些成员被修饰为private
②:内部类的实例化一定要绑定在外部类的实例上,
③:内部类可以访问外部类成员,但是内部类的成员只能在内部类范围内有效,不能被外部类使用。
◆内部类的例子
public class OutClass {
privateString str = "我是内部类";//修饰为私有
InnerClassin = new InnerClass();
publicvoid out(){
//a=4;不能直接调用内部类的成员
in.info();
}
classInnerClass{
inta = 0;
publicvoid info(){
System.out.println(str);//直接调用外部类的成员
}
}
publicstatic void main(String[] args) {
OutClasso = new OutClass();
o.out();
}
}
运行结果为:我是内部类
◆内部类的应用场景
1.向上转型为接口
如果将一个权限修饰符为private的内部类,向上转型为其父类,或者转型为一个接口,就可以在一个程序中隐藏内部类的实现细节。
public class DemoOut {
publicstatic void main(String[] args) {
Outout = new Out();
OutInterfaceinter = out.getInnerClass();
inter.desc();
}
}
interface OutInterface{
publicvoid desc();
}
class Out {
class InnerClassimplements OutInterface{
publicInnerClass(String message){
System.out.println(message);
}
@Override
publicvoid desc() {
System.out.println("内部类的方法");
}
}
publicInnerClass getInnerClass(){
returnnew InnerClass("得到内部类的对象");
}
}
运行结果为:
得到内部类的对象
内部类的方法
这样做就很好的隐藏了接口中的方法的具体逻辑
局部内部类
◆什么是局部内部类
就是在类中的局部位置定义一个类,比如方法或者任意的作用域。
◆局部内部类的语法
public classOutClass{///外部类
public void aa(){
class InnerClass{//内部类
}
}
}
◆局部内部类注意的事项
①:同成员内部类
②:如果成员内部类使用方法内的变量或形参,必须将这个变量声明为final的。这是为了让该变量超出方法的运行的声明周期。
◆局部内部类的应用实例
public class JuBuNeiBuLei {
publicvoid aa(final String str){
classInnerClass {
publicInnerClass(String message){
System.out.println(message+str);
}
}
}
}
可以看到内部类引用形参必须是final的。
◆为什么局部内部类用的局部变量和形参必须是final修饰的。
因为方法中的局部变量和形参,在方法结束之后就会被销毁,而此时局部内部类还有可能没有用到这个变量。
下面就举出一个这个例子:
publicclass JuBuNeiBuLei {
publicOutInterface2 aa(final String str){
finalString str1 = "局部变量";
classInnerClass implements OutInterface2{
publicInnerClass (String message){
System.out.println(message+str+str1);
}
@Override
publicvoid desc() {
System.out.println(str+str1);
}
}
System.out.println("方法结束了");
returnnew InnerClass("得到内部类的对象");
}
publicstatic void main(String[] args) {
OutInterface2a = new JuBuNeiBuLei().aa("形参");//到这里局部内部类引用并没有用,可是外部类方法
//已经结束了。正常来说,形参和局部变量都被销毁了,那么下面的内部类是不能用的了,可是声明为final,方法结束之后,变量
//就不会被销毁了
a.desc();
}
}
interface OutInterface2{
publicvoid desc();
}
运行结果为:
方法结束了
得到内部类的对象形参局部变量
形参局部变量
匿名内部类
◆什么是匿名内部类:
匿名内部类就是没有名字的内部类。当我们在使用一个接口或者抽象类的时候,由于他们的内部方法是没有逻辑的,而且是不能实例化的,所以我们可以通过继承来写出这个方法的逻辑。但是,是不是可以不用继承也能直接实现接口中方法的逻辑呢?答案是可以的,这个方式就是匿名内部类,这次大家明白了为什么叫匿名内部类了吧,因为它没有实现类,而是直接用一种语法实现没有方法的逻辑体
◆匿名内部类的语法:
publicvoid test(){
new接口名 (){
逻辑
没有实现的方法
};
}
大家可以看到语法中直接new了一个接口,可是接口是不能new的呀,其实这个不是new的接口,而是它的实现类,只不过这个实现类没有名字,而是直接实现了这个接口中的方法
◆匿名内部类的注意事项
①:同局部内部类
②:定义内部类的前提是必须有一个接口或者抽象类,让他实现
③:实现的接口方法不应该定义过多,否则在用匿名内部类的时候,就会导致重写的方法过多,从而影响代码的可读性和整洁性
④:匿名内部类其实就是一个匿名的实现了某一接口的子类对象。
◆匿名内部类的例子
publicclass JuBuNeiBuLei {
publicstatic void main(String[] args) {
OutInterface2 b = new OutInterface2(){
@Override
publicvoid desc() {
System.out.println("我是匿名内部类");
}
};
b.desc();
}
}
interface OutInterface2{
publicvoid desc();
}
◆匿名内部类的应用
匿名内部类通常应用在句柄函数中。具体的例子就等大家接触之后会明白的,比如集合中排序的时候,按照自己的定义规则排序,就有一个实现某接口