Java Inner Class

什么是内部类?将一个类定义在另一个类的内部,这个类就叫做内部类。

 

内部类例子

package first;
// outer class
public class OuterClass {
  
   // inner class
   class InnerClass{
      InnerClass(){
        System.out.println(OuterClass.this);
        System.out.println(this);
      }
   }
  
   public InnerClass getInnerClass(){
      return new InnerClass();
   }
  
   public static void main(String[]args) {
      OuterClass.InnerClassoic = new OuterClass().getInnerClass();
   }
}
 

Class InnerClass定义在OutClass中

 

内部类的默认作用域

还是在包first中建立如下类,

package first;
public class Caller {
   public static void main(String[]args) {
      OuterClass.InnerClassa = new OuterClass().getInnerClass();
   }
}

编译正常,可以得出结论InnerClass的作用于起码不是private,应该是protected或者public的。Protected表示包内可见

 

然后新建包second,建立如下类,

package second;
 
importfirst.OuterClass;
 
public class Caller {
   public static void main(String[]args) {
      OuterClass.InnerClassa = new OuterClass().getInnerClass();
   }
}
 

用下面的指令编译,

javac -cp ../../bin/ Caller.java
 

得到的结果是,

 

Caller.java:7: 错误: OuterClass.InnerClass在OuterClass中不是公共的; 无法从外部程序包中对其进行访问

               OuterClass.InnerClass a = new OuterClass().getInnerClass();

 

可以看出InnerClass的作用域不是公共的,也就是不是public,得出在默认情况下是protected。

 

内部类对外部来的引用

当生成一个内部类的对象的时候,它和外部类的对象之间就有了一种联系,它能访问其外围对象的所有对象。

 

修改上面的OuterClass为,

 

package first;
// outer class
public class OuterClass {
  
   public int count = 0;
   void saySomething(){
      System.out.println("youcall me~");
   }
   // inner class
   class InnerClass{
      InnerClass(){
        System.out.println(OuterClass.this);
        System.out.println(this);
      }
     
      void saySomething(){
        OuterClass.this.saySomething();
        System.out.println("youcall me!");
        count++;
      }
   }
  
   public InnerClass getInnerClass(){
      return new InnerClass();
   }
  
   public static void main(String[]args) {
      OuterClass oc = new OuterClass();
      System.out.println(oc);
      oc.getInnerClass().saySomething();
      System.out.println(oc.count);
   }
}

运行后的结果是,

first.OuterClass@1dd3812
first.OuterClass@1dd3812
first.OuterClass$InnerClass@8c436b
you call me~
you call me!
1

在调用InnerClass的saySomething方法时,调用了OuterClass的saySomething方法,也就是说明OuterClass的方法对于InnerClass是可见的。并且OuterClass的属性count对于InnerClass也是可见的。

 

再仔细观察

System.out.println(OuterClass.this);

System.out.println(oc);输出的结果是一样的,都是新生成的OuterClass对象的地址。

也就是说在InnerClass的对象中,持有了外围对象的引用,可以在内部对象中对外围对象进行操作。

 

内部类对象的初始化

上面提到了,内部对象持有了外部对象的引用,也就是说在初始化内部类的时候,外部类必须已经初始化好了。

 

来看看内部类如何初始化,修改main函数如下所示,

   public static void main(String[]args) {
      OuterClass oc= new OuterClass();
      System.out.println(oc);
      oc.getInnerClass().saySomething();
      System.out.println(oc.count);
     
      // 内部类的初始化
      OuterClass.InnerClassoic = oc.new InnerClass();
      oic.saySomething();
      System.out.println(oc.count);
   }
 

可以看出内部类初始化的格式是

 

外部类.内部类  内部类对象名 = 外部类对象.new 内部类(); (方式1)

 

如果按照我们既定的思维,

 

外部类.内部类  内部类对象名 = new 外部类.内部类(); (方式2)会出现什么情况呢?


   public static void main(String[]args) {
      OuterClass oc= new OuterClass();
      System.out.println(oc);
      oc.getInnerClass().saySomething();
      System.out.println(oc.count);
     
      // 内部类的初始化
      OuterClass.InnerClassoic = new OuterClass.InnerClass();
      oic.saySomething();
      System.out.println(oc.count);
   }
 

编译后得到如下错误,

OuterClass.java:34: 错误: 无法从静态上下文中引用非静态 变量 this

               OuterClass.InnerClass oic = new OuterClass.InnerClass();

 

因为你采用了方式2,所以Javac将OuterClass.InnerClass作为了静态内部类来处理,但是实际上它不是静态内部类,所以会出现上面的错误。之后会提到静态内部类。

 

内部类的作用

上面说了那么多关于内部类的语法,那么内部类有什么作用呢?

 

1)     内部类的对象拥有外部类的对象的引用,方便直接对外部类对象进行操作。而如果不采用内部类,将内部类提到外面单独形成一个类,那么如果想让这个类的实例(相当于内部类对象)能够操作另一个类的实例(相当于外部类对象),就需要将后者当做参数传递到前者的函数中,或者前者拥有后者的引用(作为属性)。这样就可能会出现这么一种情况,对象A将对象B作为其属性,对象B在对象A中起到工具类的作用。然后由于对象B又需要操作对象A,对象B要持有A的对象,也就是对象A也是对象B的一个属性,这就出现了我们最不想见到的相互引用。这是一个比较糟糕的设计。

2)     屏蔽某些细节的实现。如果将内部类设置为私有的,也就是加上private限定符,那么这个内部类的实现就是仅仅对于其外部类可见,不会被其他类随意调用。也很好的满足了面向对象程序设计的思想,来看看下面的例子。


package first;
 
// 计费方式
interface Billing {
   int billing();
}
 
package first;
 
public class Bus {
   class BusBillingimplements Billing{
 
      @Override
      public int billing() {
        // TODO Auto-generatedmethod stub
        return 2;
      }
   }
}
 
package first;
 
public class Tax {
   private int BASE_DIS = 2; // 起步公里数
   private int BASE_PRICE = 10; // 起步价
   private int curDis;     // 用户公里数
   private int EXCEED_PRICE = 1; // 超过起步公里后每公里的价格
  
   class TaxBillingimplements Billing{
 
      @Override
      public int billing() {
        if (curDis <=BASE_DIS){
           returnBASE_PRICE;
        }
       
        returnBASE_PRICE + (curDis -BASE_DIS) * EXCEED_PRICE;
      }
   }
}
 


对于公交车和出粗车采用了完全不一样的计费方式,并且其计费方式和外围的出行工具紧密相关。

 

3)     内部类使得多继承的解决方案变得完整。(参见java编程思想10.8)

匿名内部类

package first;
 
interface InnerClassInter {
 
}
 
package first;
// outer class
public class OuterClass {
  
   public InnerClassInter getInnerClass(){
      return new InnerClassInter(){
       
      };
   }
  
   public InnerClassIntergetInnerClass2(){
      return new InnerClassInter(){
       
      };
   }
  
   public static void main(String[] args) {
      OuterClass oc = new OuterClass();
      System.out.println(oc.getInnerClass().getClass());
      System.out.println(oc.getInnerClass2().getClass());
 
   }
}
 

在OuterClass的getInnerClass方法中,返回了一个匿名类的对象,这个匿名类没有具体的名字,其名字是JVM自动生成的。

运行后输出的结果是,

class first.OuterClass$1

classfirst.OuterClass$2

对于不同函数返回的匿名类,虽然返回的匿名类的功能完全一样,但是它们属于不同的类,所以JVM都进行了自动命名已区分这些匿名类。

 

我们熟悉的例子比如

newThread(new Runnable(){

}).start();

 

嵌套类

什么是嵌套类呢?还记得之前提到的静态内部类吗,对嵌套类就是静态内部类。如果不需要内部对象与其外围对象之间有联系,那么就可以将内部类声明为static。

这就意味着:

1)    创建内部类的对象时,不需要外部类的对象

2)    不能从嵌套类的对象访问非静态的外围对象

 

这两点都很好理解。

 

那么静态内部类如何初始化呢?

 
package first;
// outer class
public class OuterClass {
  
   public static class InnerClass implements InnerClassInter{
     
   }
  
   public static void main(String[] args) {
      OuterClass.InnerClass oic = new OuterClass.InnerClass();
   }
}
 

外部类.内部类  内部类对象名 = new 外部类.内部类();正好符合之前我们提到的创建内部类实例的方法2

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java inner join 是一种用于关系型数据库的查询操作,用于从两个或多个表返回有关联的行。 Inner join(内连接)是在两个表之间根据相关字段(通常是外键)的匹配来连接它们的行。只有当两个表的相关字段具有相同的值时,相应的行才会被连接。连接的结果是一个新的表,其包含了两个表相关字段匹配的行。 Java实现inner join的方法有多种,最常用的方法是使用JDBC(Java Database Connectivity)库来连接数据库并执行查询操作。在JDBC,可以使用SQL语句来实现inner join。下面是一个示例代码: ```java import java.sql.*; public class InnerJoinExample { public static void main(String[] args) { try { // 连接数据库 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password"); // 创建并执行inner join查询 String query = "SELECT table1.column1, table2.column2 FROM table1 INNER JOIN table2 ON table1.column3 = table2.column4"; Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query); // 处理查询结果 while (resultSet.next()) { String column1Value = resultSet.getString("column1"); String column2Value = resultSet.getString("column2"); System.out.println(column1Value + " " + column2Value); } // 关闭连接 resultSet.close(); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } ``` 以上代码演示了如何使用Java和JDBC实现inner join查询。需要注意的是,具体的SQL查询语句需要根据实际的数据库表结构和字段名来编写。 Java inner join 可以帮助我们从关联的表获取需要的数据,提供了一种灵活、可靠的方法来处理复杂的数据查询需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值