Rumah Java javaTutorial 为什么匿名内部类参数必须为final类型

为什么匿名内部类参数必须为final类型

Dec 15, 2016 pm 01:03 PM
kelas dalaman tanpa nama

1)  从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变量(形式参数或局部变量)是天经地义的.是很自然的


2)  为什么JAVA中要加上一条限制:只能访问final型的局部变量?


3)  JAVA语言的编译程序的设计者当然全实现:局部内部类能访问方法中的所有的局部变量(因为:从理论上这是很自然的要求),但是:编译技术是无法实现的或代价极高.


4)  困难在何处?到底难在哪儿? 
     局部变量的生命周期与局部内部类的对象的生命周期的不一致性!


5)  设方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i .当方法f()运行结束后,局部变量i就已死亡了,不存在了.但:局部内部类对象inner_object还可能   一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.这时:出现了一个"荒唐"结果:局部内部类对象 inner_object要访问一个已不存在的局部变量i!


6)  如何才能实现?当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量 时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以 访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了.


那么:核心的问题是:怎么才能使得:访问"复制品"与访问真正的原始的局部变量,其语义效果是一样的呢? 
当变量是final时,若是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样.语义效果相同.(若:不是final,就无法保证:复制品与原始变量保持一致了,因为:在方法中改的是原始变量,而局部内部类中改的是复制品) 

当 变量是final时,若是引用类型,由于其引用值不变(即:永远指向同一个对象),因而:其复制品与原始的引用变量一样,永远指向同一个对象(由于是 final,从而保证:只能指向这个对象,再不能指向其它对象),达到:局部内部类中访问的复制品与方法代码中访问的原始对象,永远都是同一个即:语义效 果是一样的.否则:当方法中改原始变量,而局部内部类中改复制品时,就无法保证:复制品与原始变量保持一致了(因此:它们原本就应该是同一个变量.) 

一句话:这个规定是一种无可奈何.也说明:程序设计语言的设计是受到实现技术的限制的.这就是一例. 因为:我就看到不少人都持这种观点:设计与想法是最重要的,实现的技术是无关紧要的,只要你作出设计与规定,都能实现.

 

现在我们来看,如果我要实现一个在一个方法中匿名调用ABSClass的例子: 

 public static void test(final String s){ 
     //或final String s = "axman"; 
  ABSClass c = new ABSClass(){ 
   public void m(){ 
      int x = s.hashCode();
 
      System.out.println(x);
 
   } 
  }; 
  //其它代码. 
 }
Salin selepas log masuk

从代码上看,在一个方法内部定义的内部类的方 法访问外部方法内局部变量或方法参数,是非常自然的事,但内部类编译的时候如何获取这个变量,因为内部类除了它的生命周期是在方法内部,其它的方面它就是 一个普通类。那么它外面的那个局部变量或方法参数怎么被内部类访问?编译器在实现时实际上是这样的:

public static void test(final String s){ 
     //或final String s = "axman";

  class OuterClass$1 extends ABSClass{
 
   private final String s; 
   public OuterClass$1(String s){ 
      this.s = s;    
   } 
   public void m(){ 
      int x = s.hashCode();
      System.out.println(x);
   } 
  };
  ABSClass c = new OuterClass$1(s); 
  //其它代码. 
 }
Salin selepas log masuk

即外部类的变量被作为构造方法的参数传给了内部类的私有成员.
假如没有final,那么:

 public static void test(String s){ 
     //或String s = "axman"; 
  ABSClass c = new ABSClass(){ 
   public void m(){ 
     s = "other"; 
   } 
  }; 
  System.out.println(s); 
 } 
 就会编译成: 
  public static void test(String s){ 
     //或String s = "axman";
  class OuterClass$1 extends ABSClass{
 
   private String s; 
   public OuterClass$1(String s){ 
      this.s = s;    
   } 
   public void m(){ 
     s = "other";
 
   } 
  }; 

   ABSClass c = new OuterClass$1 (s);
  }
Salin selepas log masuk

内部类的s重新指向"other"并不影响test的参数或外部定义的那个s.同理如果外部的s重新赋值内部类的s也不会跟着改变。
而你看到的

 public static void test(String s){ 
     //或String s = "axman"; 
  ABSClass c = new ABSClass(){ 
   public void m(){ 
     s = "other"; 
   } 
  }; 
  System.out.println(s); 
 }
Salin selepas log masuk

 在语法上是一个s,在内部类中被改变了,但结果打印的出来的你认为是同一的s却还是原来的"axman", 
 你能接收这样的结果吗? 
 所以final从语法上约束了实际上两个不同变量的一致性(表现为同一变量).



更多为什么匿名内部类参数必须为final类型相关文章请关注PHP中文网!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimanakah kelas dalaman tanpa nama Java menyelesaikan masalah kebocoran memori? Bagaimanakah kelas dalaman tanpa nama Java menyelesaikan masalah kebocoran memori? May 01, 2024 pm 10:30 PM

Kelas dalaman tanpa nama boleh menyebabkan kebocoran memori Masalahnya ialah mereka memegang rujukan kepada kelas luar, menghalang kelas luar daripada dikumpul. Penyelesaian termasuk: 1. Gunakan rujukan yang lemah Apabila kelas luar tidak lagi dipegang oleh rujukan yang kuat, pemungut sampah akan segera mengitar semula objek rujukan yang lemah memerlukan ingatan semasa pengumpulan sampah Hanya kemudian objek rujukan lembut dikitar semula. Dalam pertempuran sebenar, seperti dalam aplikasi Android, masalah kebocoran memori yang disebabkan oleh kelas dalaman tanpa nama boleh diselesaikan dengan menggunakan rujukan yang lemah, supaya kelas dalaman tanpa nama boleh dikitar semula apabila pendengar tidak diperlukan.

Apakah corak reka bentuk untuk kelas dalaman tanpa nama di Jawa? Apakah corak reka bentuk untuk kelas dalaman tanpa nama di Jawa? May 02, 2024 pm 04:42 PM

Kelas dalaman tanpa nama ialah kelas dalaman khas dalam Java yang tidak mempunyai nama eksplisit dan dicipta melalui ungkapan baharu Ia digunakan terutamanya untuk melaksanakan antara muka tertentu atau melanjutkan kelas abstrak dan digunakan serta-merta selepas penciptaan. Corak reka bentuk kelas dalaman tanpa nama biasa termasuk: Corak penyesuai: menukar satu antara muka kepada antara muka yang lain. Corak Strategi: Mentakrifkan dan Menggantikan Algoritma. Corak pemerhati: Daftar pemerhati dan kendalikan peristiwa. Ia sangat berguna dalam aplikasi praktikal, seperti menyusun TreeSet mengikut panjang rentetan, mencipta benang tanpa nama, dsb.

Apakah kelebihan kelas dalaman tanpa nama di Jawa? Apakah kelebihan kelas dalaman tanpa nama di Jawa? Apr 30, 2024 am 11:39 AM

Kelas dalaman tanpa nama digunakan di Java sebagai kelas dalaman khas yang memudahkan subkelas, memudahkan kod dan mengendalikan acara (seperti klik butang). Kes praktikal termasuk: Pengendalian acara: Gunakan kelas dalaman tanpa nama untuk menambah pendengar acara klik untuk butang. Transformasi data: Isih koleksi menggunakan kaedah Collections.sort dan kelas dalaman tanpa nama sebagai pembanding.

Apakah kitaran hayat kelas dalaman tanpa nama Java? Apakah kitaran hayat kelas dalaman tanpa nama Java? May 01, 2024 pm 04:06 PM

Jangka hayat kelas dalam tanpa nama ditentukan oleh skopnya: Kaedah-kelas dalam tempatan: Sah hanya dalam skop kaedah yang menciptanya. Kelas dalaman pembina: terikat kepada contoh kelas luar dan dikeluarkan apabila tika kelas luar dikeluarkan. Kelas dalaman statik: dimuatkan dan dipunggah pada masa yang sama dengan kelas luaran.

Apakah kesilapan biasa dengan kelas dalaman tanpa nama di Jawa? Apakah kesilapan biasa dengan kelas dalaman tanpa nama di Jawa? May 02, 2024 am 09:03 AM

Ralat penggunaan kelas dalaman tanpa nama: Mengakses pembolehubah di luar skop menggunakan menangkap pengecualian yang tidak diisytiharkan dalam persekitaran bukan benang selamat

Bagaimana untuk mengoptimumkan prestasi kelas dalaman tanpa nama Java? Bagaimana untuk mengoptimumkan prestasi kelas dalaman tanpa nama Java? May 02, 2024 am 08:48 AM

Masalah prestasi kelas dalaman tanpa nama ialah ia dicipta semula setiap kali ia digunakan, yang boleh dioptimumkan melalui strategi berikut: 1. Simpan kelas dalaman tanpa nama dalam pembolehubah tempatan 2. Gunakan kelas dalaman bukan statik; ungkapan. Ujian praktikal menunjukkan bahawa pengoptimuman ekspresi lambda mempunyai kesan terbaik.

Apakah alternatif kepada kelas dalaman tanpa nama di Jawa? Apakah alternatif kepada kelas dalaman tanpa nama di Jawa? Apr 30, 2024 pm 01:15 PM

Ungkapan Lambda, sebagai alternatif kepada kelas dalaman tanpa nama, menyediakan cara yang lebih ringkas untuk mentakrifkan pelaksanaan antara muka berfungsi: gunakan sintaks pendek (parameter)->ungkapan untuk mentakrifkan fungsi tanpa nama. Sesuai untuk situasi di mana antara muka berfungsi perlu dilaksanakan (hanya satu kaedah abstrak). Boleh memudahkan tugas seperti menyusun senarai dan definisi benang.

Dalam senario apakah kelas dalaman tanpa nama Java tidak sesuai untuk digunakan? Dalam senario apakah kelas dalaman tanpa nama Java tidak sesuai untuk digunakan? May 03, 2024 pm 05:42 PM

Kelas dalaman tanpa nama tidak sesuai digunakan apabila: perlu mengakses ahli persendirian, memerlukan berbilang contoh, memerlukan warisan, perlu mengakses jenis generik

See all articles