一个java内部类有几个分类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个java内部类有几个分类?相关的知识,希望对你有一定的参考价值。

参考技术A

共有四种内部类,分别是:

1.常规内部类

2.静态内部类

3.局部内部类

4.匿名内部类

常规内部类:常规内部类没有用static修饰且定义在在外部类类体中。

常规内部类中的方法可以直接使用外部类的实例变量和实例方法。在常规内部类中可以直接用内部类创建对象。

静态内部类:与类的其他成员相似,可以用static修饰内部类,这样的类称为静态内部类。静态内部类与静态内部方法相似,只能访问外部类的static成员,不能直接访问外部类的实例变量,与实例方法,只有通过对象引用才能访问。

由于static内部类不具有任何对外部类实例的引用,因此static内部类中不能使用this关键字来访问外部类中的实例成员,但是可以访问外部类中的static成员。这与一般类的static方法相通。

局部内部类:在方法体或语句块(包括方法、构造方法、局部块或静态初始化块)内部定义的类成为局部内部类。局部内部类不能加任何访问修饰符,因为它只对局部块有效。

局部内部类只在方法体中有效,就想定义的局部变量一样,在定义的方法体外不能创建局部内部类的对象

在方法内部定义类时,应注意以下问题:
1.方法定义局部内部类同方法定义局部变量一样,不能使用private、protected、public等访问修饰说明符修饰,也不能使用static修饰,但可以使用final和   abstract修饰
2.方法中的内部类可以访问外部类成员。对于方法的参数和局部变量,必须有final修饰才可以访问。
3.static方法中定义的内部类可以访问外部类定义的static成员

匿名内部类:定义类的最终目的是创建一个类的实例,但是如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到与一起完成,或者说在定义类的同时就创建一个类。以这种方法定义的没有名字的类成为匿名内部类。

C++ 父子类的用法

【中文标题】C++ 父子类的用法【英文标题】:C++ Parent and Child class usage 【发布时间】:2016-07-04 21:55:42 【问题描述】:

假设我有一个Person 课程。这个人类持有Shape

Shape 父类有几个从它派生的子类。例如RectangleCircle。这些子类中的每一个都有自己的方法。例如,Circle 类有GetRadius(),而 Rectangle 类有GetWidth() 以及更多特定于这种形状的方法。

现在假设我有几个人,其中一些人持有矩形,其他人持有圆形。我想知道每个人都拿着什么形状,我想从这些形状中获取信息。但是我不能这样做,因为 Person 持有一个 Shape,所以它不能访问任何子特定的方法。

我读过一些关于铸造的东西,但我发现它有点令人困惑,我不确定铸造是否是最好的方法,或者是否有更有效的方法来完全解决这个问题。那我该怎么做呢?

编辑 1:编辑以获得更多说明。 我希望GetWidth()GetRadius() 等方法返回不同的类型。

【问题讨论】:

作为您想要用来解决这些问题的快速指针。您需要使用动态绑定。在 C++ 中,这是通过指针和 virtual 关键字实现的。在这种情况下,您必须在每个子类中调用提供信息GetRadius()GetWidth() 相同名称的函数,例如getShapeInfo()getShapeInfo() 也将在 Shape 中定义。您可能会将getShapeInfo() 设为纯虚函数。含义 Shape 是一个抽象类。这是因为,世界上没有形状,只有形状类型的东西,比如圆形。 所以Shape 中的'virtual double getShapeInfo()` 和每个Person 都会有一个Shape *s 以允许动态绑定,然后当CircleRect 也被指向时调用s->getShapeInfo() 将调用圆形或矩形函数,具体取决于s 所指向的对象的类型 @izaak_pyzaak 如果它们返回不同的类型怎么办?来自CirclegetShapeInfo() 将返回双倍半径,但是我希望来自RectanglegetShapeInfo() 返回类似于vec2 的东西,包含宽度和高度。 您可以定义一个新类型ShapeInfo,它从两者都返回。虽然,这在某种程度上将反射问题转移到了一种新类型上,以使函数调用看起来更整洁。但是你不知道谁会保持什么样的形状,这可能是要走的路。你读到的关于铸造的东西是关于向下铸造的危险吗?最终,如果你有两个不同的函数并在一个矩形上调用getRadius,那么坏事就会接踵而至。 @JohnCake 您有一些答案应该可以回答您的大部分问题。尤其是Sam Varshavchik provided那一个。 【参考方案1】:

Shape 超类至少有一个虚拟方法,您当然可以使用dynamic_cast 来确定超类的每个实例是哪个子类。这当然是可能的,有时这是正确的做法,但大多数时候并非如此。

相反,正确的做法是提前设计你的类,以这样一种方式,任何操作都可以用任何Shape 完成,它有一个Shape 方法,通常是虚拟的。最低的共同点是拥有一个由每个子类实现的纯虚方法,它返回一个特定子类的标识符。

但是,一般来说,如果您需要知道超类的实例是什么特定的子类,则说明类层次结构设计不正确。确实,生活并非一直都是 100% 完美的。有时为了处理棘手的情况,可能有必要诉诸这种丑陋的东西。但这不应该是一开始的计划。您应该尝试正确设计您的类层次结构,这样就没有必要了。

即使是最小的公分母:

A) 上述函数返回某个枚举标识符,该标识符对应于超类是哪个特定子类,并且

B) 超类定义了所有超类可以实现的所有可能的虚方法,默认实现会引发异常

可以以不涉及丑陋演员的方式做到这一点。

【讨论】:

您能否给我一段示例代码,说明您将如何设计我提出的这种情况?既然我已经看到了 James Adkison 发布的代码,那么您给出的选项 B 显然是我可以做到的一种方式,但是如果我错了,请纠正我,您的帖子说我应该更好地设计类层次结构而不是那样做。但我自己真的想不出来。 A) 和 B) 不是相互排斥的,我的意思是指出一种使用它们的潜在方法:指示超类是哪个子类的实例,以及子类的可访问方法虚方法。而且,是的,最好重新考虑一个人的阶级层次结构。【参考方案2】:

如果您有一个Shape 类型的指针,其中包含RectangleCircle 等子类型的对象,那么您可以使用dynamic_cast 来检查对象的类型在运行时。 dynamic_cast 将允许您安全地检查其地址由指针保存的对象的运行时类型。

请查看https://en.wikipedia.org/wiki/Run-time_type_information#dynamic_cast 了解如何完成此操作的示例。

【讨论】:

【参考方案3】:

您可以通过在Shape 类上为适用于所有派生类的任何函数声明virtual 函数来避免强制转换。在这种情况下,您想知道每个派生类型是什么,以便您可以拥有一个getType() 函数。您不必完全按照这种方式进行操作,但以下是您可以如何操作的示例。

示例代码

#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Shape

public:
    virtual ~Shape() 

    virtual Shape* clone() const = 0;

    virtual std::string getType() const = 0;
;

class Circle : public Shape

public:
    virtual Circle* clone() const override  return new Circle(*this); 

    virtual std::string getType() const override  return "Circle"; 
;

class Rectangle : public Shape

public:
    virtual Rectangle* clone() const override  return new Rectangle(*this); 
    virtual std::string getType() const override  return "Rectangle"; 
;

class Person

public:
    explicit Person(const std::string& name, const Shape& shape) :
        mName(name),
        mShape(shape.clone())
    
    

    std::string mName;
    std::unique_ptr<Shape> mShape;
;

int main()

    std::vector<Person> people;
    people.emplace_back("Foo", Circle());
    people.emplace_back("Bar", Rectangle());

    for (const auto& person : people)
    
        std::cout << person.mName << " with " << person.mShape->getType() << "\n";
    

    return 0;

示例输出

Foo with Circle
Bar with Rectangle

Live Example

【讨论】:

以上是关于一个java内部类有几个分类?的主要内容,如果未能解决你的问题,请参考以下文章

请问JAVA中匿名内部类有啥用,举个例子,谢谢

Java面试题|静态内部类和非静态内部类有什么区别?

Java 内部类有坑。。100 % 内存泄露!

Java内部类有坑,100%内存泄露!

Java内部类有坑,100%内存泄露!

内部类和静态内部类有什么区别?