简介
类的高级特性 这一章主要是介绍了java中的包,final修饰词,内部类三个知识点.需要重点掌握和熟悉的是内部类以及final修饰词这2个用法。
- final关键字
final修饰词在java日常开发中用到的太多了,如父类使用final修饰,子类无法继承.修饰方法.子类继承中无法重写.否则编译器就不认可这种写法.类似的还有final修饰的变量,不可修改,必须要初始化(需要注意的一些基本数据类型 存在一些默认值,实际上已经隐藏初始化了.) - 内部类
另外还有就是内部类的知识点(书上将这一部分的特性在swing开发中用到的比较多,网页开发用到的比较少.实际上还真是这样.平时内部类用到最多的就是mybatis中使用generator特性生成的查询语句的使用上了.)内部类根据使用方式上可以分为对象内部类+静态内部类.实例内部类其实就是属于对象的内部类,而静态内部类就是属于类的内部类.根据类型的不同 内部类的创建方式也不同,使用方式上也有区别。
java类包
这个知识点比较简单,实际上就是每个类都有属于特定的包,类似java.util.Date类,就属于java.util包.包的主要目的在于 java中同样类名的java文件太多了,所以在区分java文件的区分条件上加了一层,除了java文件名外,再加上个包名。
这样就能更好的区分不同的java文件了.类似上面的Date类,这是属于java.util。同样的java.sql.Date中也存在一个Date,2者之间区分就在于包名上.所以在导入不同的java文件时,不仅要区分java名,还要区分包名. 包名 的导入使用import关键字(在Java文件首行非注释代码写上所属的包)
- import关键字.上面说过有关import的作用的 是将引用的类或者方法导入当前类中,可以通过.*的方式 将某个包下面所有的包 全都导进去,也可以精确到导入某个包的常量等。
- 包名. java包的命名规则是全部使用小写字母.虽然使用大写没啥问题。但是很不优雅规范,感觉这个码农技术就很差,辣鸡,所以这个坏习惯要改.
final关键字
final说白了就是修改的内容不可以被改变.像类不能被修改继承,方法不能被重写,变量不能被重新赋值.
- final变量.final修饰的变量不能被修改.声明的同时赋值操作.否则编译器会报错。有一种情况 刚开始学的同学可能会认为有问题,就是声明了变量之后 通过构造方法赋值,其实是没问题的.声明的如果是对象或数组同样 不能修改.类似像数组+集合这种容器的不能够重新实例化,但是容器里面的元素却是可以改变的.但有一个例外就是string字符串对象,因为String字符串的设定就是 字符串内容改变即对象改变。所以不能像集合数组容器一样.同时需要注意的一点是static final修饰的常量 必须在定义的时候就赋值.
package finaldemo;
import java.util.Random;
import com.sun.accessibility.internal.resources.accessibility;
public class FinalData {
static Random rand = new Random();
private final int VALUE_1 = 9;
final int BLANK_FANALVALUE;// 空白final值 声明同时使用构造方法赋值
private final Test test = new Test();
private Test test2 = new Test();
private final int[] a = { 1, 2, 3, 4, 5 };
private String string = "111";
private final int i4 = rand.nextInt(20);
private static final int i5 = rand.nextInt(20);
@Override
public String toString() {
return i4 + "," + i5;
}
public FinalData(int bLANK_FANALVALUE) {
super();
BLANK_FANALVALUE = bLANK_FANALVALUE;
}
public static void main(String[] args) {
FinalData data = new FinalData(1);
// data.test=new Test(); final不能重新赋值
data.test2 = new Test();// 没有final修饰的变量
data.string = "22";
// data.VALUE_1++;final
// 因为数组是对象 所以只要指向数组的引用类型不变即可,里面的内容是可以变的.
data.a[0] = 3;
// data.a=new int[]{111};//数组对象 引用类型改变 错误
}
}
- final方法.final修饰的方法不能被重写.有个前提就是 首先得继承的到,不然实际上子类就是新写的一个方法.
Parent
package finaldemo;
public class Parent {
private final void doit() {// 私有final类
}
final void doit1() {// final类 不可修改
}
public void doit2() {// 可以重写 继承
}
}
Sub
package finaldemo;
public class Sub extends Parent {
/**
* 子类方法 不属于重写 因为压根没继承过来
*/
private final void doit() {
}
// 不能重写 因为父类方法使用final修饰
// final void doit1(){
//
// }
public void doit2() {
}
}
- final类.使用final修饰的类 不能被修改.也就是不能被继承。IDE编辑器 压根不让继承.实际上这就是面向对象编程的类封装实现,可以对外隐藏或开放细节实现的关键所在.
内部类
内部类分为 成员内部类、局部内部类、匿名内部类、静态内部类。根据内部类是否属于内部类是否可以调用外部类的成员变量属性、内部类是否有自己的名称区分.(之前只知道这么个概念,之前是只在单例模式中使用到过.)
成员内部类。内部类可以使用外部类的成员变量及方法.而外部类不能使用内部类的成员变量及方法.(主要是内部类的创建依赖外部内的非静态方法及).
package inner.demo;
public class OuterClass {
InnerClass innerClass = new InnerClass();
private class InnerClass {
public InnerClass() {
super();
}
public void inf() {
}
int y = 4;
}
private void ouf() {
}
private InnerClass doit() {
innerClass.y = 0;
System.out.println(innerClass.y);
return new InnerClass();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
InnerClass innerClass1 = outerClass.new InnerClass();
System.out.println(innerClass1.y);
InnerClass innerClass2 = outerClass.doit();
System.out.println(innerClass2.y);
}
}
从上面的例子可以印证了 内部类的创建需要从外部类或外部类的非静态方法2种方式.外部类使用内部类 首先需要实例化内部类.
- 内部类向上造型为接口
既然内部类和外部类同样是类,那么外部类中出现的如继承,多态等特性在内部类中同样也会出现.同时非内部类 无法使用private及pritected修饰(重点).
OuterInterface接口
package inner.demo;
public interface OuterInterface {
public void f();
}
OuterClass2含有内部类的外部类
package inner.demo;
public class OuterClass2 {
public class InnerClass2 implements OuterInterface {
public InnerClass2() {
super();
}
public void f() {
System.out.println("内部类实现接口的重写方法");
}
}
public InnerClass2 doit() {
System.out.println("通过外部类的非静态方法创建内部类");
return new InnerClass2();
}
}
IterfaceInner测试内部类向上造型的demo
package inner.demo;
public class IterfaceInner {
public static void main(String[] args) {
OuterClass2 outerClass2=new OuterClass2();
OuterInterface outerInterface=outerClass2.doit();
outerInterface.f();
}
}
运行结果
- 使用this关键字获取内部类与外部类的引用
this关键字主要用于成员变量与局部变量名发生冲突的时候,加了this.xx的变量表示当前调用对象的变量,说白了就是成员变量。而在内部类与外部类的使用过程中也有可能出现外部类的变量与内部类的变量名发生冲突的时候,这个时候就需要使用this去区分,但是可能存在冲突 所以就需要 类名.this.xx的方式表示 外部类的成员变量,this.xxx表示内部类的成员变量.
package inner.demo;
public class TheSameName {
private int x;
private class InnerClass{
private int x;
public InnerClass() {
super();
}
public InnerClass(int x) {
super();
this.x = x;
}
public void doit(){
this.x=TheSameName.this.x;
}
}
}
局部内部类/匿名内部类
上面说完成员内部类,这个局部内部类及匿名内部类无非就是创建形式上的不同,特性上与成员内部类上一致,创建依赖外部类或外部类 非静态方法。内部类可以直接调用外部类的成员方法和参数. (内部类使用上需要注意一点 外部类中成员方法 不能直接返回内部类,否则编译器报错,一般是通过接口的方式实现)
局部内部类实现方式
package inner.demo;
import org.omg.CORBA.PUBLIC_MEMBER;
public class OuterClass3 {
public OuterInterface doit() {
//外部类中成员方法中创建内部类 这种内部类称为局部内部类
class InnerClass implements OuterInterface{
public InnerClass() {
super();
}
public void f() {
System.out.println("内部类实现外部接口 实现成员方法中向上造型");
}
}
return new InnerClass();
}
}
匿名内部类案例
package inner.demo;
public class OuterClass4 {
public OuterClass4 doit() {
// 匿名内部类没有 内部类名 直接返回类似外部类构造方法的东西
return new OuterClass4() {
private int a = 0;
private int getA() {
return this.a;
}
};
}
}
静态内部类
静态内部类顾名思义 就是静态的内部类,不需要外部类的实例化就可以创建的内部类,同时对于外部类的使用 也是基于static修饰词的特性,只能使用外部类的静态变量和方法.
package inner.demo;
public class OuterClass5 {
static int a = 1;
int b = 2;
static void amethod() {
System.out.println("静态方法");
}
void bmethod() {
System.out.println("成员方法");
}
static private class InnerClass5 {
int c1 = a;
// int c2 = b; 静态内部类无法使用外部类 成员变量及方法
public InnerClass5() {
super();
}
public static void doit() {
amethod();
// bmethod();
}
}
}
总结
从看完十一章的内容到写完这篇博客总结 好了一天的时间,时间好长呀。感觉这样不是快速学习的节奏,虽然学的挺扎实的但是还是要提高效率,不要一会玩手机 一会看书。这样效率太差了。
这篇主要讲了类包,final修饰词,用于修饰类 方法 变量,总的来讲就是不可以修改.而内部类 主要是在一个类中创建2个类的解决方法.分为成员内部类,局部内部类,匿名内部类,静态内部类。成员内部类中需要注意的就是 非静态方法中返回内部类 一般都是以内部类实现的接口,通过向上造型的特性加以实现的。同时像外部类中存在的特性如继承 多态 封装等特性 内部类同样有的,无非就是类创建的方式 位置有所不同,使用修饰词及创建方式,可以使用的数据不同的差别。其实感觉可以把内部类当做是外部类的子类。这样子类用父类的成员变量及方法 就好理解多了.