java编程思想第四版第十章总结
时间:2022-07-25
本文章向大家介绍java编程思想第四版第十章总结,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
1. 内部类的特性
- 他允许你把一些逻辑相关的类组织在一起。
2. 使用.this
- 如果你需要在内部类中堆外部类进行应用,可以使用外部类的名字后面加.this。下面展示了如何使用 .this
package net.mindview.innerclasses;
public class DotThis {
void f(){
System.out.println("DotThis.f()");
}
public class Inner {
public DotThis outer() {
System.out.println(DotThis.this);
return DotThis.this;
}
}
public Inner inner(){
return new Inner();
}
public static void main(String[] args) {
DotThis dt = new DotThis();
DotThis.Inner di = dt.inner();
di.outer().f();
}
}
3.使用.new
- 如果想要创建某个外部类的内部类,可以使用外部类对象.new 内部类:
- 如果想new一个内部类, 不能使用外部类.new 内部类。必须使用外部类的对象来创建内部类的对象。 用法如下:
package net.mindview.innerclasses;
public class DotNew {
public class Inner {
}
public static void main(String[] args) {
DotNew dn = new DotNew();
DotNew.Inner di = dn.new Inner();
}
}
4. 方法的内部类
- 这里只说两点:
- 方法的内部类有效作用域是在方法内,方法外部可以调用
- 方法的内部类,并不是说方法被调用的时候才创建了,实际上,这个类和其他类没有什么不同,他们在使用之前,已经经过编译了.
package net.mindview.innerclasses;
/**
* 方法内部类的作用域就在方法内,方法外不可以访问.
* @author samsung
*
*/
public class Parcel5 {
public Destination destination(String s){
//在方法里定义了一个内部类
class PDestination implements Destination{
private String label;
public PDestination(String label){
System.out.println(this);
this.label = label;
}
@Override
public String readLabel() {
return label;
}
}
return new PDestination(s);
}
public static void main(String[] args) {
Parcel5 p = new Parcel5();
System.out.println(p.destination("上海").readLabel());
System.out.println(p.destination("北京").readLabel());
}
/**
* 注意:PDestination定义在方法里面,并不是说只有调用方法的时候,这个类才被创建.
* 实际上,这个类和其他类一样,已经经过编译了.
*/
}
5. 定义在作用域内的内部类, 此作用域在方法的内部.
- 定义在方法作用域内部的类, 只在作用域内部有效
package net.mindview.innerclasses;
public class Parcel6 {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s){
id = s;
}
String getSlip(){
return id;
}
}
TrackingSlip ts = new TrackingSlip("100");
String s = ts.getSlip();
}
//作用域外不可使用
//TrackingSlip ts = new TrackingSlip("100");
}
public void track(){
internalTracking(true);
}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
}
6.匿名内部类
- 默认构造器匿名内部类
package net.mindview.innerclasses;
public class Parcel7 {
public Contents contents(){
//定义了一个匿名内部类.将返回值和创建类放在了一起
return new Contents(){
private int i = 11;
@Override
public int value() {
return i;
}
};
}
public static void main(String[] args) {
Parcel7 p = new Parcel7();
Contents c = p.contents();
System.out.println(c.value());
}
}
- 代参数构造器的匿名内部类
package net.mindview.innerclasses;
public class Wrapping {
private int i;
public Wrapping(int x){
this.i = x;
}
public int value(){
return i;
}
}
package net.mindview.innerclasses;
public class Parcel8 {
public Wrapping wrapping(int x){
return new Wrapping(x){
@Override
public int value(){
return super.value()*47;
}
};
}
public static void main(String[] args) {
Parcel8 p = new Parcel8();
Wrapping w = p.wrapping(20);
System.out.println(w.value());
}
}
- 这里需要注意的是, 虽然Wrapping是一个导出类, 却依然被当成了一个接口来使用.
package net.mindview.innerclasses;
public class Wrapping {
private int i;
public Wrapping(int x){
this.i = x;
}
public int value(){
return i;
}
}
- 匿名内部类中使用外部对象, 这外部的这个对象必须是final的
package net.mindview.innerclasses;
public class Parcel9 {
public Destination destination(final String x){
final String m = null;
//匿名内部类
return new Destination(){
//在内部类中使用到了外部的对象
private String label = m;
private String abc = x;
@Override
public String readLabel() {
return label;
}
};
}
public static void main(String[] args) {
Parcel9 p = new Parcel9();
System.out.println(p.destination("20").readLabel());
}
/**
* 定义一个匿名内部类, 如果希望在匿名内部类中使用外部的对象,
* 那么编译器要求外部类的这个参数必须是final的. 如果你没有将这个类定义为final
* 编译器会报错
*/
}
- 在匿名内部类中使用类似构造器的行为. 我们知道匿名内部类没有类名, 因此他不可能有命名构造器. 但通过实例初始化可,就鞥够达到为匿名内部类创建一个构造器的效果
package net.mindview.innerclasses;
abstract class Base{
public Base(int i){
System.out.println("Base构造器, i=" + i);
}
public abstract void f();
}
public class AnonymousConstructor {
/**
* 此处的i不要求是final的,因为这个i只是传递给了匿名
* 变量的构造器,并没有在匿名内部类内部使用.
*/
public static Base getBase(int i){
return new Base(i){
{
System.out.println("这里可以类似构造器进行初始化");
}
@Override
public void f() {
System.out.println("匿名函数f()");
}
};
}
public static void main(String[] args) {
AnonymousConstructor amc = new AnonymousConstructor();
amc.getBase(100).f();
}
}
7. 再谈工厂设计模式.
再上一章中说了工厂设计模式. 本书中的案例是对象工厂设计模式. 来看看是怎么写的
package net.mindview.innerclasses.factory.MethodFactory;
/**
* 服务类
*/
interface Service{
void method1();
void method2();
}
/**
* 工厂类
*/
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service{
@Override
public void method1() {
System.out.println("Implementation1 method1");
}
@Override
public void method2() {
System.out.println("Implementation1 method1");
}
}
class Implementation2 implements Service{
@Override
public void method1() {
System.out.println("Implementation2 method1");
}
@Override
public void method2() {
System.out.println("Implementation2 method1");
}
}
class ImplementationFactory1 implements ServiceFactory{
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation1();
}
}
class ImplementationFactory2 implements ServiceFactory{
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation2();
}
}
public class Factories {
public static void serviceSustomer(ServiceFactory factory){
factory.getService().method1();
factory.getService().method2();
}
public static void main(String[] args) {
serviceSustomer(new ImplementationFactory1());
serviceSustomer(new ImplementationFactory2());
}
}
我们还可以将这种方式以内部类的方式来实现
package net.mindview.innerclasses.factory.methodFactoryInnerClass;
/**
* 服务类
*/
interface Service{
void method1();
void method2();
}
/**
* 工厂类
*/
interface ServiceFactory {
Service getService();
}
/**
* 每一种服务,提供一种工厂. 这种工厂专门创建这种服务.
*/
class Implementation1 implements Service{
private Implementation1(){}
@Override
public void method1() {
System.out.println("Implementation1 method1");
}
@Override
public void method2() {
System.out.println("Implementation1 method1");
}
//让工厂在内部实现
public static ServiceFactory factory = new ServiceFactory(){
@Override
public Service getService() {
return new Implementation1();
}
};
}
class Implementation2 implements Service{
@Override
public void method1() {
System.out.println("Implementation2 method1");
}
@Override
public void method2() {
System.out.println("Implementation2 method1");
}
//让工厂在内部实现
public static ServiceFactory factory = new ServiceFactory(){
@Override
public Service getService() {
return new Implementation2();
}
};
}
public class Factories {
public static void serviceSustomer(ServiceFactory factory){
factory.getService().method1();
factory.getService().method2();
}
public static void main(String[] args) {
serviceSustomer(Implementation1.factory);
serviceSustomer(Implementation2.factory);
}
}
我的理解是: 第一种工厂的含义是: 我现在需要一种服务, 然后我找到对应的工厂, 为我提供服务. 工厂再去找对应这种服务的实体.
而第二种方式呢, 我现在需要服务. 直接就去找这种服务对应的工厂就可以了. 也就是工厂内置了. 就像大公司下有多个子公司, 每个子公司都有自己的工厂.我要那种类型的东西,他就自己给生产了
8. 嵌套类
如果内部类对象预期外围类对象之间不需要有联系, 那么可以将内部类声明为static的。这种累通常称为嵌套类。要想理解static定义的内部类的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建他的外围类对象。然而,当内部类是static的时候, 就不是这样了。嵌套类意味着:
- 要创建嵌套类的对象, 并不需要外围类的对象。
- 不能从嵌套类的对象中访问非静态的对象
- 普通的内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以有这些东西 观看上面说的文字,会有些难以理解,所以, 将这段代码敲一遍,就理解什么意思了。动手很重要啊
package net.mindview.innerclasses;
public class Parcel11 {
//ParcelContent被定义为static的,所以是一个嵌套类
private static class ParcelContent implements Contents {
int i = 11;
@Override
public int value() {
return i;
}
}
//ParcelDestination 是一个嵌套类. 被定义为static的.所以,它内部可以的有static的成员和方法
private static class ParcelDestination implements Destination {
private String label;
private ParcelDestination(String label){
this.label = label;
}
@Override
public String readLabel() {
return label;
}
public static void f(){
System.out.println(AnotherLabel.x);
//b()方法是访问不到的
//AnotherLabel.b();
}
static int x = 10;
//他是嵌套在嵌套类内部的嵌套类.
static class AnotherLabel{
//内部定义了两个和外部一样的成员方法, 竟然不冲突
public static void f(){
System.out.println("这时静态类的静态方法");
}
static int x = 10;
//嵌套类中的非静态方法不能被外部访问到. 所以这个方法没有任何意义
public void b(){
System.out.println("这时静态类中的静态方法b()");
}
}
}
public static Contents getContents(){
return new ParcelContent();
}
public static Destination getDestination(String s){
return new ParcelDestination(s);
}
public static void main(String[] args) {
System.out.println(getContents().value());
System.out.println(getDestination("北京").readLabel());
//嵌套类中,不能访问非静态方法
//ParcelDestination.readLabel();
//但是可以方法静态方法
ParcelDestination.f();
//嵌套类的使用方式是,类似于静态方法. 将其作为静态方法来使用.
ParcelDestination.AnotherLabel.x=1;
System.out.println(ParcelDestination.AnotherLabel.x);
ParcelDestination.AnotherLabel.f();
//下面这样写是不对的
//ParcelDestination.AnotherLabel.b();
}
}
9. 接口内部的类
- 首先,接口里不能放置任何代码, 但是嵌套类可以.
- 你放到接口中的任何类都自动式public static的.
- 你可以在内部类中实现外围类的接口. 示例如下: 注意, 如果想运行main方法, 这里的嵌套类必须是static的.
package net.mindview.innerclasses;
/**
* 定义在接口内部的类
*/
public interface ClassInInterface {
void howdy();
//这里static必须是显示标记出来的,否则这个类将不能运行
static class Test implements ClassInInterface {
@Override
public void howdy() {
System.out.println("Howdy!");
}
public static void main(String[] args) {
Test t = new Test();
t.howdy();
}
}
}
- 如果想创建某些公共代码, 使得他们可以被某个接口的所有实现类所共用, 那么使用接口内部的嵌套类会显得很方便.
- 例如: 我们可以在每个类中写一个mian方法用来测试这个类, 这样做有一个缺点, 那就是要写好多遍,而且, 必须通过编译器的编译, 我们可以使用嵌套类改善 再说的白话一点,就是在接口中定义一个这样的嵌套类. 然后定义mian方法, 在main方法中使用嵌套类. 当有一个新的对象继承了这个类的时候, 就在这个类中的main方法进行测试就好了. 这样的好处是, 当我打包发布到正式环境的时候, 我想删除所有的main方法,因为他们的存在也会被编译器编译, 降低效率. 如果只有一个接口的嵌套类中定义的main方法,那么删起来就方便很多了。不明白的话,在看下面这个例子,就懂了
package net.mindview.innerclasses;
/**
* 定义在接口内部的类
*/
public interface ClassInInterface {
void howdy();
//这里static必须是显示标记出来的,否则这个类将不能运行
static class Test implements ClassInInterface {
@Override
public void howdy() {
System.out.println("Howdy!");
}
public static void main(String[] args) {
//测试第一个实现了接口的类
ClassInInterface t = new Test();
t.howdy();
//测试第二个实现了接口的类
ClassInInterface t1 = new ClassInInterfaceTest();
t1.howdy();
}
}
}
package net.mindview.innerclasses;
public class TestBed {
public void f(){
System.out.println("f()");
}
static class Testers{
public static void main(String[] args) {
TestBed t = new TestBedTest();
t.f();
}
}
}
- 接口中嵌套类如何创建实例化对象。 参考习题20
package net.mindview.innerclasses.test20;
interface InnerInInterface{
static class Inner{
public Inner(){
System.out.println("嵌套类构造方法");
}
}
}
public class Test20 {
public static void main(String[] args) {
//直接使用 new 外围类.嵌套类
InnerInInterface.Inner inner = new InnerInInterface.Inner();
}
}
10. 从多层嵌套类中访问外部类的成员
注意下面这个例子是如何创建内部类的。
package net.mindview.innerclasses;
/**
* 多层嵌套类访问外部成员
*/
class A{
private void f(){};
class B{
private void b(){};
class C {
void c(){
f();
b();
};
}
}
}
public class MutliNestingAccess {
public static void main(String[] args) {
A a = new A();
A.B b = a.new B();
A.B.C c = b.new C();
c.c();
}
}
iooo
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 聊聊Golang逃逸分析
- 结构型设计模式:适配器模式和门面模式
- 结构型设计模式:代理模式
- kubernete中的原子调度单位:pod
- mybatis-generator在命令行及IEAD中的使用
- mybatis-generator在命令行及IDEA中的使用
- 70-STM32+ESP8266+AIR202基本控制篇-移植使用-移植单片机MQTT底层包到自己的工程项目
- springboot研究:springboot自带监控actuator
- springboot研究:springboot使用swagger自动构建api
- numpy/pandas瞎搞系列(一):OLS,WLS的numpy实现
- redis实战第三篇 redis sentinel安装和部署
- 后浪,谈谈你对jvm性能调优的理解
- Homer预测共表达基因的motif
- redis实战第一篇 安装和使用
- lombok在java项目中的使用