什么叫Java中的前向引用?

时间:2013-01-24 19:46:43

标签: java

我已经通过this question on legality of forward references ,但不清楚Java语言中forward references的含义。有人可以借助一个例子来解释吗?

4 个答案:

答案 0 :(得分:14)

这特别是编译错误。它的全部都是关于类变量声明的排序。我们将一些代码用于说明目的:

public class ForwardReference {        
   public ForwardReference() {
      super();
   }

   public ForwardReference echoReference() {
      return this;
   }

   public void testLegalForwardReference() {
      // Illustration: Legal
      this.x = 5;
   }

   private int x = 0;

   // Illustration: Illegal
   private ForwardReference b = a.reference();
   private ForwardReference a = new ForwardReference();
}

正如您所看到的,Java允许您在类方法中引用类变量,即使变量的声明在之后 >方法。这是(合法)前向引用的示例,对此的支持内置于Java编译器中。

不能 做的是声明一个类变量'a',它取决于尚未声明的另一个类变量'b'。依赖类变量声明必须以它们的依赖性的相反顺序出现。

在切线上,如果您的代码包含非法引用错误,大多数(如果不是全部)IDE都会发出警告。

JLS的section 8.3.2.3涵盖了非法的正向引用。

答案 1 :(得分:3)

如果你有

,它基本上只是编译器读取内容的顺序
int c = 3
int a = b;
int b = 5;

编译器将从上到下读取它,因此它将是第一行,它声明一个变量'c',并将其赋值为3,这很好,然后它将遇到第二行,它声明变量'a',然后尝试将其分配给'b'。

但是现在,编译器有一个问题:这个'b'是什么东西?它还只学习了'c',而且最近才知道'a',但是它没有任何关于'b'的知识,因为对于编译器来说,它还没有被声明。那么,既然编译器无法处理所有的混淆,它就会停止,并让你知道你做了什么来激怒它。

因此,前向参考部分将是对尚不存在的东西的引用。及时前进..

答案 2 :(得分:1)

简单来说,它意味着在代码文件中进一步向下引用(访问变量,调用函数)。

   static int x=getY();
   static int y=5;
   static int getY() { return y; }
  • x的值设置为getY()
  • 的结果
  • 在y的值设置为5
  • 之前调用getY()
  • x的值因此为0(默认整数)
  • y的值是5

答案 3 :(得分:1)

import random
import tkinter as tk

root = tk.Tk()
user_input = tk.Entry(root)
user_input.pack()

greetings = ['hola', 'hello', 'hi', 'Hi', 'hey!', 'hey']
question = ['How are you?', 'How are you doing?']
responses = ['Okay', "I'm fine"]
huh = "I did not understand what you said"

def cb():
    user_text = user_input.get()
    if user_text in greetings:
        bot_text = random.choice(greetings)
    elif user_text in question:
        bot_text = random.choice(responses)
    else:
        bot_text = huh
    output.config(text=bot_text)

button = tk.Button(root, text="Enter", command=cb)
button.pack()

output = tk.Label(root, text='')
output.pack()

tk.mainloop()

*********参考案例 - 1 *********

不允许使用前向引用实例变量,因为编译器不确定我们正在引用的值的类型,或者甚至可能没有这样的变量。

考虑一个例子: -

import random
import tkinter as tk

root = tk.Tk()
user_input = tk.Entry(root)
user_input.pack()

greetings = ['hola', 'hello', 'hi', 'Hi', 'hey!', 'hey']
question = ['How are you?', 'How are you doing?']
responses = ['Okay', "I'm fine"]
huh = "I did not understand what you said"

def cb(event):
    user_text = user_input.get()
    if user_text in greetings:
        bot_text = random.choice(greetings)
    elif user_text in question:
        bot_text = random.choice(responses)
    else:
        bot_text = huh
    output.config(text=bot_text)

user_input.bind("<Return>", cb)
output = tk.Label(root, text='')
output.pack()

tk.mainloop()

如果在上述情况下允许前向引用,那么它可能会造成严重破坏。

public class AnyCode {

    void print() {
        System.out.println("Value of j - " + j);   // legal
        System.out.println("Value of i  - " + i);  // legal
    }

    // CASE - 1 
    int k = i;         // illegal
    int i; 

    // CASE - 2 
    int l = j;         // legal
    static int m = j;  // illegal
    static int j;

    // CASE - 3 
    A aObj = bObj;     // illegal
    B bObj = new B();

    public static void main(String[] args) {

        /* 
           Note :- here anyCode act as a local variable and get space on stack 
           whereas the object it is referring to is present on heap. And you 
           cannot forward reference a local variable. 
        */

        anyCode.print();    // 'Cannot find symbol' error
        AnyCode anyCode = new AnyCode();
    }

}

class A {

}

class B {

}

在上面的例子中我决定不宣布b,现在如果java允许这样的赋值,那么它将是一场噩梦。

**********请参阅案例 - 2 *********

静态变量在实例变量之前加载,因此转发引用静态变量并将它们分配给实例变量是完全正确的