第十一章 类的高级特性

JAVA笔记

1.之前做的笔记都在word上,发现翻得不方便,然后有些重要的代码打进去又不好看了,所以就在博客里写笔记吧。
2.用的是清华大学出版社Java从入门到精通第4版
3.现在学到第十一章,就从第十一章开始,前面的有时间再从word上copy过来。

类的高级特性

Java类包

Java中提供了一种管理文件的机制,就是类包。

完整的类路径

1.一个完整的类名需要包名与类名的组合,每个类都隶属于一个类包,只要保证同一类包中的类不同名,就可以有效地避免同名类冲突的情况。
2. 完整的类名:java.lang.Math,其中java.lang为包的名称,Math为类的名称。

  • 例1
  • 在程序中使用两个不同Data类的完整类路径,可以使用如下代码
java.util.Data data = new java.util,Data();
java.sql.Data data2 = new java.sql.Data(233);
  1. 同一个包中的类不必存放在同一个位置,只要将CLASSPATH分别指向这两个位置即可。

创建包

  1. java包的命名规则是全部使用小写字母
  2. 在类中定义报名的语法如下:
package 包名

导入包

使用import关键字导入包

语法如下:

import com.lzw.*; //指定com.lzw包中的所有类在程序中都可以使用
//或
import com.lzw.Math;//指定com.lzw包中的Math类在程序中可以使用
  1. 如果类定义中已经导入com.lzw.Math类,在类体中再使用其他包中的Math类时则必须指定完整的带有包格式的类名。
  2. 当使用import指定了一个包中的所有类时,并不会指定这个包的子包中的类,如果用到这个包中的子类,需要再次对子包作单独引用。
使用import导入静态成员
  1. 使用import导入静态成员的语法如下:
import static 静态成员
  • 例2
  • 在项目中创建ImportTest类,在该类中使用import关键字导入静态成员
package com.lzw;
import static java.lang.Math.*;
import static java.lang.System.*;

public class ImportTest {
	public static void main(String[] args) {
		// 在主方法中可以直接使用这些静态成员
		out.println("1和4的较大值为:" + max(1, 4));
	}
}

final变量

  1. 通常,由final定义的变量为常量。被定义为final的常量定义时需要使用大写字母命名,并且中间使用下划线进行连接。
  2. 一个被定义为final的对象引用只能指向唯一一个对象,不可以将它再指向其他对象,但是一个对象本身的值却是可以改变的,那么为了使一个常量真正做到不可更改,可以讲常量声明为static final。
  • 例3
  • final与static final
package com.lzw;

import static java.lang.System.*;

import java.util.*;

public class FinalStaticData {
	private static Random rand = new Random(); // 实例化一个Random类对象
	// 随机产生0~10之间的随机数赋予定义为final的a1
	private final int a1 = rand.nextInt(10);
	// 随机产生0~10之间的随机数赋予定义为static final的a2
	private static final int a2 = rand.nextInt(10);
	
	public static void main(String[] args) {
		FinalStaticData fdata = new FinalStaticData(); // 实例化一个对象
		// 调用定义为final的a1
		out.println("重新实例化对象调用a1的值:" + fdata.a1);
		// 调用定义为static final的a2
		out.println("重新实例化对象调用a1的值:" + fdata.a2);
		// 实例化另外一个对象
		FinalStaticData fdata2 = new FinalStaticData();
		out.println("重新实例化对象调用a1的值:" + fdata2.a1);
		out.println("重新实例化对象调用a2的值:" + fdata2.a2);
	}
}
  • 结果
    在这里插入图片描述
    由上可看出,定义为final的常量不是恒定不变的,将随机数赋予定义为final的常量,可以做到每次运行程序时改变a1的值。但是a2与a1不同,由于它被声明为static final形式,所以在内存中为a2开辟了一个恒定不变的区域,当再次实例化一个对象时,仍然只想a2这块内存区域,所以a2的值保持不变。
  1. 在java中定义全局变量,通常使用public static final修饰,这样的常量只能在定义时被赋值。

final方法

将方法定义为final类型可以防止子类修改该类的定义与实现方式,同时定义为final的方法的执行效率要高于非final方法。一个定义为private的方法隐式被指定为final类型,这样无需将一个定义为private的方法再定义为final类型。

final类

  1. 定义为final 的类不能被继承,也不允许其他人对这个类进行任何改动。
  2. 如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式(变量可改)。

内部类

 内部类可分为成员内部类、局部内部类以及匿名类

成员内部类

成员内部类简介
  1. 内部类可以随意使用外部类的成员方法以及成员变量,尽管这些成员被修饰为private。
  2. 内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
  • 例4
public class OuterClass {
	innerClass in = new innerClass(); // 在外部类实例化内部类对象引用
	
	public void ouf() {
		in.inf(); // 在外部类方法中调用内部类方法
	}
	
	class innerClass {
		innerClass() { // 内部类构造方法
		}
		
		public void inf() { // 内部类成员方法
		}
		
		int y = 0; // 定义内部类成员变量
	}
	
	public innerClass doit() { // 外部类方法,返回值为内部类引用
		// y=4; //外部类不可以直接访问内部类成员变量
		in.y = 4;
		return new innerClass(); // 返回内部类引用
	}
	
	public static void main(String args[]) {
		OuterClass out = new OuterClass();
		// 内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现
		OuterClass.innerClass in = out.doit();
		OuterClass.innerClass in2 = out.new innerClass();
	}
}

  1. 如果在外部类和非静态方法之外实例化内部类对象,需要使用外部类.内部类的形式指定该对象的类型。
内部类向上转型为接口
这个书本上写得比较杂,但也懂了那个意思。
就是private的内部类继承接口,并重写接口里的方法,然后外部调用时,可以访问内部类重写的接口方法。
  • 废话不说,上代码
package com.lzw;

interface OutInterface { // 定义一个接口
	public void f();
}

public class InterfaceInner {
	public static void main(String args[]) {
		OuterClass2 out = new OuterClass2(); // 实例化一个OuterClass2对象
		// 调用doit()方法,返回一个OutInterface接口
		OutInterface outinter = out.doit();
		outinter.f(); // 调用f()方法
	}
}

class OuterClass2 {
	// 定义一个内部类实现OutInterface接口
	private class InnerClass implements OutInterface {
		InnerClass(String s) { // 内部类构造方法
			System.out.println(s);
		}
		
		public void f() { // 实现接口中的f()方法
			System.out.println("访问内部类中的f()方法");
		}
	}
	
	public OutInterface doit() { // 定义一个方法,返回值类型为OutInterface接口
		return new InnerClass("访问内部类构造方法");
	}
}

在这里插入图片描述

使用this关键字获取内部类与外部类的引用
  • 一言不合上代码
public class TheSameName {
	private int x;
	
	private class Inner {
		private int x = 9;
		public void doit(int x) {
			x++; // 调用的是形参x
			this.x++; // 调用内部类的变量x
			TheSameName.this.x++; // 调用外部类的变量x
		}
	}
}

局部内部类

内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可定义内部类。
interface OutInterface2 { // 定义一个接口
}
class OuterClass3 {
	public OutInterface2 doit(final String x) { // doit()方法参数为final类型
		// 在doit()方法中定义一个内部类
		class InnerClass2 implements OutInterface2 {
			InnerClass2(String s) {
				s = x;
				System.out.println(s);
			}
		}
		return new InnerClass2("doit");
	}
}

内部类是doit()方法的一部分,并非OuterClass3类中的一部分,所以在doit()方法的外部不能访问该内部类。

匿名内部类

这一段有点莫名其妙,似懂非懂,不知道有啥用,以后用着再查吧- -!记个语法
return new A(){
...//内部类体
};

静态内部类

  1. 一个静态内部类中可以声明static成员,但是在非静态内部类中不可以声明静态成员
  2. 静态内部类不可以使用外部类的非静态成员
  3. 如果创建静态内部类,不需要起外部类的对象
  4. 不能从静态内部类的对象中访问非静态外部类的对象
    进行程序测试时,可以将测试用的主方法写入静态内部类中,当完成测试需要将.class文件打包时,只要删除StaticInnerClass$Inner独立类即可

内部类的继承

  • 代码
public class OutputInnerClass extends ClassA.ClassB{
	public OutputInnerClass(ClassA a){
		a.super();
	}
}
class ClassA{
	class ClassB{
	}
}

在某个类继承内部类时,必须硬性给予这个类一个带参数的构造方法,并且该构造方法的参数为需要继承内部类的外部类的引用,同时在构造方法体中使用a.super()语句,这样采薇继承提供了必要的对象引用。

实践与练习

 行了,要来点真材实料了。

1. 尝试在方法中编写一个匿名内部类

【= =刚说以后用着再查,这个以后好快啊- -!,我都麻了,视频教学1分钟没到,说以后会说道,现在知道有这么个东西就好了,关于匿名内部类给大家教到这里。。。】
行了,网上查了下匿名内部类,和书上的例子不太一样,但大概知道了这么回事
chenssy的java提高篇(十)-----详解匿名内部类 有说。


public class e1 {
	public static void text(t1 t) {
		System.out.println(t.getName() + ' ' + t.age());
	}

	public static void main(String[] args) {
		e1.text(new t1() {
			int age() {
				return 22;
			}
		});

	}

}

abstract class t1 {
	String name = "muhua";

	abstract int age();

	String getName() {
		return name;
	}
}

仿照chennssy的blog的例子的。然后匿名内部类在e1.text那。
再看看答案

public class AnonymityInnerClass {
}
class OuterClass4{

	public OutInterface doit(final String s){
		return new OutInterface(){
			private int i=0;
			public int getValue(){
				System.out.println(s);
				return i;
				
			}
			public void f(){
				System.out.println("f()");
			}
		};
	}

}
interface OutInterface { // 定义一个接口
}

答案是用的接口,然后也是在return处(和书本一样)设置匿名内部类。

2将主方法编写到静态内部类中,然后在DOS中编译运行,注意编译后出现的.class文件

直接就用书上的代码了

package com.lzw;

public class StaticInnerClass {
	int x=100;
	static class Inner{
		void doitInner(){
			//System.out.println("外部类"+x);
		}
		public static void main(String args[]){
			System.out.println("a");
		}
	}
}

= =然后,忘了DOC怎么操作了,行吧,再查查怎么用DOC运行。
出现错误在这里插入图片描述,是注
释部分出现错误,不管,直接去掉注释部分。
出现这两个!在这里插入图片描述在这里插入图片描述
和书本一样,可以在 测试时用

3编写一个静态内部类,在主方法中创建其内部类的实例


public class e3 {
	static class inner {
		char a;
		static int b = 10;

		inner(char a) {
			this.a = a;
		}

		void show() {
			System.out.println(a + "  " + b);
		}
	}

	public static void main(String[] args) {
		e3 x = new e3();
		e3.inner y = new e3.inner('w');
		y.show();
	}

}

有点粗糙,就这样了

  • 答案

public class UseCase3 {
	static class a{
		void f(){
			System.out.println("f()");
		}
	}
	public static void main(String args[]){
		UseCase3.a a=new a();
		a.f();
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值