final keyword
- Categories: modified class can not be inherited.
- Methods: The modified method can not be overridden.
- Variables: modified variables can not be reassigned.
final keyword is used to modify a class
Format:
public class class name Final {
// ...
}
Meaning: The current class can not have any subclasses.
Note: A class that is final, then the method in which all the members can not be overwritten
Code demonstrates
demo01 Package; // the modified final class public final class MyClass / * the extends Object * / { public void Method () { the System. OUT .println ( " method performs! " ); } }
a method used to modify the final keyword
Format:
modifier final return type method name (parameter list) {
// Method member
}
Meaning: This method is the final method, that can not be overwritten.
Precautions:
- For classes, methods, for, abstract and final keyword keyword can not be used, because the contradictions
Code demonstrates
public Final void Method () { System.out.println ( "Final Method!" ); }
modification of a local variable final keyword
After the final modification, it can only be assigned once and can not be changed.
// declare variables, using the final modified final int A; // first assignment A = 10 ; // second assignment A = 20; // error, can not be reassigned
After the final modification, can only point to an object, the memory address value can not be changed. But it does not affect the internal value of the object's member variables to modify the code as
// Create a User object fianl modified Final User = U new new User (); // create another User object U = new new User (); // error, pointing to the new object, the value of the address change. // call the setName method u.setName ( "Joe Smith"); // can be modified
Keyword final modifications member variables
Meaning: this variable is also still are immutable.
Precautions:
- As the member variables have a default value, followed by the final must be manually assigned, the default value will not give up.
- For the final member variable, using either direct assignment or assignment by the constructor. Both choose one.
- Among the class constructor must ensure that all overloaded, all ultimately have the final member variable assignment.
Code demonstrates
public class the Person { // direct assignment public Final int Age = 18 is ; public Final String name; // constructor, assignment public the Person (String name) { the this .name = name; } }
Permissions modifier
- public: public.
- protected: Protected
- default: default
- private: private
Visible, public has the greatest authority. private is the least privilege.
- Member variables private, hidden details.
- Constructor uses public, easy to create the object.
- Members method uses public, easy to call the method.
Inner classes
What is the inner class
Internal class classification
- Members of the inner class
- Partial inner classes (including anonymous inner classes)
Members of the inner class
修饰符 class 外部类名称 {
修饰符 class 内部类名称 {
// ...
}
// ...
}
代码演示
package demo02; public class Body { // 外部类 public class Heart { // 成员内部类 // 内部类的方法 public void beat() { System.out.println("心脏跳动:蹦蹦蹦!"); //内部类访问外部类成员 System.out.println("我叫:" + name); // 正确写法! } } // 外部类的成员变量 private String name; // 外部类的方法 public void methodBody() { System.out.println("外部类的方法"); // 在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。 new Heart().beat(); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
访问特点
- 内部类可以直接随便访问外部类的成员,包括私有成员。
- 外部类要访问内部类的成员,有两种方式:
package demo02; /* 如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。 例如:身体和心脏的关系。又如:汽车和发动机的关系。 */ public class Demo01InnerClass { public static void main(String[] args) { Body body = new Body(); // 外部类的对象 // 通过外部类的对象,调用外部类的方法,里面间接在使用内部类Heart body.methodBody(); System.out.println("====================="); // 按照公式写: Body.Heart heart = new Body().new Heart(); heart.beat(); } }
代码执行后的结果
内部类重名现象
怎么区分重名问题,如下代码所示
package cn.itcast.day11.demo03; // 如果出现了重名现象,那么格式是:外部类名称.this.外部类成员变量名 public class Outer { int num = 10; // 外部类的成员变量 public class Inner /*extends Object*/ { int num = 20; // 内部类的成员变量 public void methodInner() { int num = 30; // 内部类方法的局部变量 System.out.println(num); // 局部变量,就近原则 System.out.println(this.num); // 内部类的成员变量 System.out.println(Outer.this.num); // 外部类的成员变量 } } }
局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
定义格式:
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
// ...
}
}
}
注意:
定义一个类的时候,权限修饰符规则:
- 外部类:public / (default)
- 成员内部类:public / protected / (default) / private
- 局部内部类:什么都不能写
代码演示
class Outer { public void methodOuter() { class Inner { // 局部内部类 int num = 10; public void methodInner() { System.out.println(num); // 10 } } Inner inner = new Inner(); inner.methodInner(); } }
注意:
局部内部类的final问题
备注:从Java 8+开始,只要局部变量事实不变,那么final关键字可以省略。
原因:
- new出来的对象在堆内存当中。
- 局部变量是跟着方法走的,在栈内存当中。
- 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
- 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。
代码演示
public class MyOuter { public void methodOuter() { int num = 10; // 所在方法的局部变量 class MyInner { public void methodInner() { System.out.println(num); } } } }
匿名内部类(属于局部内部类中的一种)
- 定义实现类
- 重写接口中的全部抽象方法
- 创建实现类对象
- 调用重写后的方法
前提
- 匿名内部类必须继承一个父类或者实现一个父接口。
格式解析:
- new代表创建对象的动作
- 接口名称就是匿名内部类需要实现哪个接口
- {...}这才是匿名内部类的内容
另外还要注意几点问题:
- 匿名内部类,在【创建对象】的时候,只能使用唯一一次。如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
- 匿名对象,在【调用方法】的时候,只能调用唯一一次。如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
- 匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】强调:匿名内部类和匿名对象不是一回事!!!
代码演示
定义接口
package demo03; public interface FlyAble { public abstract void fly(); }
package demo03; public class InnerDemo { public static void main(String[] args) { /*1.等号右边:是匿名内部类,定义并创建该接口的子类对象 2.等号左边:是多态赋值,接口类型引用指向子类对象 */ FlyAble f = new FlyAble() { public void fly() { System.out.println("我飞了~~~"); } };//调用 fly方法,执行重写后的方法 f.fly(); } } }
package demo03; public class Test { public static void main(String[] args) { /*创建匿名内部类,直接传递给showFly(FlyAble f) */ showFly(new FlyAble() { public void fly() { System.out.println("我飞了~~~"); } }); } //接口作为参数 public static void showFly(FlyAble f) { f.fly();//我飞了~~~ } }
引用类型用法总结
class作为成员变量
- 类作为成员变量时,对它进行赋值的操作,实际上,是赋给它该类的一个对象。
interface作为成员变量
- 接口作为成员变量时,对它进行赋值的操作,实际上,是赋给它该接口的一个子类对象。
interface作为方法参数和返回值类型
- 接口作为参数时,传递它的子类对象。
- 接口作为返回值类型时,返回它的子类对象。
class作为方法参数和返回值类型
- 在编写程序中,会经常碰到调用的方法要接收的是一个类类型的情况,那么这时,要向方法中传入该类的对象,或者子类对象。
- 写程序调用方法时,我们以后会经常碰到返回一个类类型的返回值,那么这时,该方法要返回一个该类的对象,或者子类对象。
抽象类作为方法参数与返回值
- 开发中,抽象类作为方法参数的情况也很多见。当遇到方法参数为抽象类类型时,要传入一个实现抽象类所有抽象方法的子类对象。
- 抽象类作为方法返回值的情况,也是有的,这时需要返回一个实现抽象类所有抽象方法的子类对象。