Java内部类详解

Java中的四种访问权限(private,public,protected,无修饰) /实体类属性和数据库字段名称不一致//实体类属性和数据库字段名称不一致return id;return age;emp.test();//直接调用public修饰的变量//private修饰的变量进行赋值//调用private修饰的变量1、public修饰符定义的属性和方法通过对象实例化进行调用,2、private修饰的属性通过set、get方法进行调用。 阅读详情

Java内部类详解

  说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉。原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法。今天我们就来一探究竟。下面是本文的目录大纲:

  一.内部类基础

  二.深入理解内部类

  三.内部类的使用场景和好处

  四.常见的与内部类相关的笔试面试题

  若有不正之处,请多谅解并欢迎批评指正。

  请尊重作者劳动成果,转载请标明原文链接:

  http://www.cnblogs.com/dolphin0520/p/3811445.html

一.内部类基础

  在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。

  1.成员内部类

  成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
class  Circle {
     double  radius =  0 ;
     
     public  Circle( double  radius) {
         this .radius = radius;
     }
     
     class  Draw {      //内部类
         public  void  drawSahpe() {
             System.out.println( "drawshape" );
         }
     }
}

  这样看起来,类Draw像是类Circle的一个成员,Circle称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class  Circle {
     private  double  radius =  0 ;
     public  static  int  count = 1 ;
     public  Circle( double  radius) {
         this .radius = radius;
     }
     
     class  Draw {      //内部类
         public  void  drawSahpe() {
             System.out.println(radius);   //外部类的private成员
             System.out.println(count);    //外部类的静态成员
         }
     }
}

  不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

1
2
外部类. this .成员变量
外部类. this .成员方法

  虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class  Circle {
     private  double  radius =  0 ;
 
     public  Circle( double  radius) {
         this .radius = radius;
         getDrawInstance().drawSahpe();    //必须先创建成员内部类的对象,再进行访问
     }
     
     private  Draw getDrawInstance() {
         return  new  Draw();
     }
     
     class  Draw {      //内部类
         public  void  drawSahpe() {
             System.out.println(radius);   //外部类的private成员
         }
     }
}

  成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public  class  Test {
     public  static  void  main(String[] args)  {
         //第一种方式:
         Outter outter =  new  Outter();
         Outter.Inner inner = outter. new  Inner();   //必须通过Outter对象来创建
         
         //第二种方式:
         Outter.Inner inner1 = outter.getInnerInstance();
     }
}
 
class  Outter {
     private  Inner inner =  null ;
     public  Outter() {
         
     }
     
     public  Inner getInnerInstance() {
         if (inner ==  null )
             inner =  new  Inner();
         return  inner;
     }
      
     class  Inner {
         public  Inner() {
             
         }
     }
}

  内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

  2.局部内部类

  局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class  People{
     public  People() {
         
     }
}
 
class  Man{
     public  Man(){
         
     }
     
     public  People getWoman(){
         class  Woman  extends  People{    //局部内部类
             int  age = 0 ;
         }
         return  new  Woman();
     }
}

  注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

  3.匿名内部类

  匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段Android事件监听代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scan_bt.setOnClickListener( new  OnClickListener() {
             
             @Override
             public  void  onClick(View v) {
                 // TODO Auto-generated method stub
                 
             }
         });
         
         history_bt.setOnClickListener( new  OnClickListener() {
             
             @Override
             public  void  onClick(View v) {
                 // TODO Auto-generated method stub
                 
             }
         });

  这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。这段代码中的:

1
2
3
4
5
6
7
8
new  OnClickListener() {
             
             @Override
             public  void  onClick(View v) {
                 // TODO Auto-generated method stub
                 
             }
         }

  就是匿名内部类的使用。代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private  void  setListener()
{
     scan_bt.setOnClickListener( new  Listener1());       
     history_bt.setOnClickListener( new  Listener2());
}
 
class  Listener1  implements  View.OnClickListener{
     @Override
     public  void  onClick(View v) {
     // TODO Auto-generated method stub
             
     }
}
 
class  Listener2  implements  View.OnClickListener{
     @Override
     public  void  onClick(View v) {
     // TODO Auto-generated method stub
             
     }
}

  这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和static修饰符的。

  匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

  4.静态内部类

  静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  class  Test {
     public  static  void  main(String[] args)  {
         Outter.Inner inner =  new  Outter.Inner();
     }
}
 
class  Outter {
     public  Outter() {
         
     }
     
     static  class  Inner {
         public  Inner() {
             
         }
     }
}

  

二.深入理解内部类

  1.为什么成员内部类可以无条件访问外部类的成员?

  在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译字节码文件看看究竟。事实上,编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面是Outter.java的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  class  Outter {
     private  Inner inner =  null ;
     public  Outter() {
         
     }
     
     public  Inner getInnerInstance() {
         if (inner ==  null )
             inner =  new  Inner();
         return  inner;
     }
      
     protected  class  Inner {
         public  Inner() {
             
         }
     }
}

  编译之后,出现了两个字节码文件:

  反编译Outter$Inner.class文件得到下面信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
E:\Workspace\Test\bin\com\cxh\test2>javap -v Outter$Inner
Compiled from  "Outter.java"
public  class  com.cxh.test2.Outter$Inner  extends  java.lang.Object
   SourceFile:  "Outter.java"
   InnerClass:
    # 24 = # 1  of # 22 ;  //Inner=class com/cxh/test2/Outter$Inner of class com/cxh/tes
t2/Outter
   minor version:  0
   major version:  50
   Constant pool:
const  # 1  =  class         # 2 ;      //  com/cxh/test2/Outter$Inner
const  # 2  = Asciz        com/cxh/test2/Outter$Inner;
const  # 3  =  class         # 4 ;      //  java/lang/Object
const  # 4  = Asciz        java/lang/Object;
const  # 5  = Asciz         this $ 0 ;
const  # 6  = Asciz        Lcom/cxh/test2/Outter;;
const  # 7  = Asciz        <init>;
const  # 8  = Asciz        (Lcom/cxh/test2/Outter;)V;
const  # 9  = Asciz        Code;
const  # 10  = Field       # 1 .# 11 ;  //  com/cxh/test2/Outter$Inner.this$0:Lcom/cxh/t
est2/Outter;
const  # 11  = NameAndType # 5 :# 6 ; //  this$0:Lcom/cxh/test2/Outter;
const  # 12  = Method      # 3 .# 13 ;  //  java/lang/Object."<init>":()V
const  # 13  = NameAndType # 7 :# 14 ; //  "<init>":()V
const  # 14  = Asciz       ()V;
const  # 15  = Asciz       LineNumberTable;
const  # 16  = Asciz       LocalVariableTable;
const  # 17  = Asciz        this ;
const  # 18  = Asciz       Lcom/cxh/test2/Outter$Inner;;
const  # 19  = Asciz       SourceFile;
const  # 20  = Asciz       Outter.java;
const  # 21  = Asciz       InnerClasses;
const  # 22  =  class        # 23 ;     //  com/cxh/test2/Outter
const  # 23  = Asciz       com/cxh/test2/Outter;
const  # 24  = Asciz       Inner;
 
{
final  com.cxh.test2.Outter  this $ 0 ;
 
public  com.cxh.test2.Outter$Inner(com.cxh.test2.Outter);
   Code:
    Stack= 2 , Locals= 2 , Args_size= 2
    0 :   aload_0
    1 :   aload_1
    2 :   putfield        # 10 ;  //Field this$0:Lcom/cxh/test2/Outter;
    5 :   aload_0
    6 :   invokespecial   # 12 ;  //Method java/lang/Object."<init>":()V
    9 :    return
   LineNumberTable:
    line  16 :  0
    line  18 :  9
 
   LocalVariableTable:
    Start  Length  Slot  Name   Signature
    0       10       0     this        Lcom/cxh/test2/Outter$Inner;
 
 
}

  第11行到35行是常量池的内容,下面逐一第38行的内容:

final com.cxh.test2.Outter this$0;

  这行是一个指向外部类对象的指针,看到这里想必大家豁然开朗了。也就是说编译器会默认为成员内部类添加了一个指向外部类对象的引用,那么这个引用是如何赋初值的呢?下面接着看内部类的构造器:

public com.cxh.test2.Outter$Inner(com.cxh.test2.Outter);

  从这里可以看出,虽然我们在定义的内部类的构造器是无参构造器,编译器还是会默认添加一个参数,该参数的类型为指向外部类对象的一个引用,所以成员内部类中的Outter this&0 指针便指向了外部类对象,因此可以在成员内部类中随意访问外部类的成员。从这里也间接说明了成员内部类是依赖于外部类的,如果没有创建外部类的对象,则无法对Outter this&0引用进行初始化赋值,也就无法创建成员内部类的对象了。

  2.为什么局部内部类和匿名内部类只能访问局部final变量?

  想必这个问题也曾经困扰过很多人,在讨论这个问题之前,先看下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public  class  Test {
     public  static  void  main(String[] args)  {
         
     }
     
     public  void  test( final  int  b) {
         final  int  a =  10 ;
         new  Thread(){
             public  void  run() {
                 System.out.println(a);
                 System.out.println(b);
             };
         }.start();
     }
}

  这段代码会被编译成两个class文件:Test.class和Test 1.class。默认情况下,编译器会为匿名内部类和局部内部类起名为Outter 1.class。默认情况下,编译器会为匿名内部类和局部内部类起名为Outterx.class(x为正整数)。

  

  根据上图可知,test方法中的匿名内部类的名字被起为 Test$1。

  上段代码中,如果把变量a和b前面的任一个final去掉,这段代码都编译不过。我们先考虑这样一个问题:

  当test方法执行完毕之后,变量a的生命周期就结束了,而此时Thread对象的生命周期很可能还没有结束,那么在Thread的run方法中继续访问变量a就变成不可能了,但是又要实现这样的效果,怎么办呢?Java采用了 复制  的手段来解决这个问题。将这段代码的字节码反编译可以得到下面的内容:

  我们看到在run方法中有一条指令:

bipush 10

  这条指令表示将操作数10压栈,表示使用的是一个本地局部变量。这个过程是在编译期间由编译器默认进行,如果这个变量的值在编译期间可以确定,则编译器默认会在匿名内部类(局部内部类)的常量池中添加一个内容相等的字面量或直接将相应的字节码嵌入到执行字节码中。这样一来,匿名内部类使用的变量是另一个局部变量,只不过值和方法中局部变量的值相等,因此和方法中的局部变量完全独立开。

  下面再看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
public  class  Test {
     public  static  void  main(String[] args)  {
         
     }
     
     public  void  test( final  int  a) {
         new  Thread(){
             public  void  run() {
                 System.out.println(a);
             };
         }.start();
     }
}

  反编译得到:

  我们看到匿名内部类Test$1的构造器含有两个参数,一个是指向外部类对象的引用,一个是int型变量,很显然,这里是将变量test方法中的形参a以参数的形式传进来对匿名内部类中的拷贝(变量a的拷贝)进行赋值初始化。

  也就说如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。

  从上面可以看出,在run方法中访问的变量a根本就不是test方法中的局部变量a。这样一来就解决了前面所说的 生命周期不一致的问题。但是新的问题又来了,既然在run方法中访问的变量a和test方法中的变量a不是同一个变量,当在run方法中改变变量a的值的话,会出现什么情况?

  对,会造成数据不一致性,这样就达不到原本的意图和要求。为了解决这个问题,java编译器就限定必须将变量a限制为final变量,不允许对变量a进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。

  到这里,想必大家应该清楚为何 方法中的局部变量和形参都必须用final进行限定了。

  3.静态内部类有特殊的地方吗?

  从前面可以知道,静态内部类是不依赖于外部类的,也就说可以在不创建外部类对象的情况下创建内部类的对象。另外,静态内部类是不持有指向外部类对象的引用的,这个读者可以自己尝试反编译class文件看一下就知道了,是没有Outter this&0引用的。

三.内部类的使用场景和好处

  为什么在Java中需要内部类?总结一下主要有以下四点:

  1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,

  2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。

  3.方便编写事件驱动程序

  4.方便编写线程代码

  个人觉得第一点是最重要的原因之一,内部类的存在使得Java的多继承机制变得更加完善。

四.常见的与内部类相关的笔试面试题

 1.根据注释填写(1),(2),(3)处的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public  class  Test{
     public  static  void  main(String[] args){
            // 初始化Bean1
            ( 1 )
            bean1.I++;
            // 初始化Bean2
            ( 2 )
            bean2.J++;
            //初始化Bean3
            ( 3 )
            bean3.k++;
     }
     class  Bean1{
            public  int  I =  0 ;
     }
 
     static  class  Bean2{
            public  int  J =  0 ;
     }
}
 
class  Bean{
     class  Bean3{
            public  int  k =  0 ;
     }
}

  从前面可知,对于成员内部类,必须先产生外部类的实例化对象,才能产生内部类的实例化对象。而静态内部类不用产生外部类的实例化对象即可产生内部类的实例化对象。

  创建静态内部类对象的一般形式为:  外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()

  创建成员内部类对象的一般形式为:  外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()

  因此,(1),(2),(3)处的代码分别为:

  View Code

 

  View Code

 

  View Code

2.下面这段代码的输出结果是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public  class  Test {
     public  static  void  main(String[] args)  {
         Outter outter =  new  Outter();
         outter. new  Inner().print();
     }
}
 
 
class  Outter
{
     private  int  a =  1 ;
     class  Inner {
         private  int  a =  2 ;
         public  void  print() {
             int  a =  3 ;
             System.out.println( "局部变量:"  + a);
             System.out.println( "内部类变量:"  +  this .a);
             System.out.println( "外部类变量:"  + Outter. this .a);
         }
     }
}
  View Code

 

  最后补充一点知识:关于成员内部类的继承问题。一般来说,内部类是很少用来作为继承用的。但是当用来继承的话,要注意两点:

  1)成员内部类的引用方式必须为 Outter.Inner.

  2)构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。这段代码摘自《Java编程思想》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class  WithInner {
     class  Inner{
         
     }
}
class  InheritInner  extends  WithInner.Inner {
      
     // InheritInner() 是不能通过编译的,一定要加上形参
     InheritInner(WithInner wi) {
         wi. super ();  //必须有这句调用
     }
  
     public  static  void  main(String[] args) {
         WithInner wi =  new  WithInner();
         InheritInner obj =  new  InheritInner(wi);
     }
}

 

 参考资料:

  《java编程思想》

  http://www.cnblogs.com/chenssy/p/3388487.html

  http://blog.youkuaiyun.com/zhangjg_blog/article/details/20000769

  http://blog.youkuaiyun.com/zhangjg_blog/article/details/19996629

  http://blog.youkuaiyun.com/zhaoqianjava/article/details/6849812

  http://www.cnblogs.com/nerxious/archive/2013/01/24/2875649.html

 

作者: 海子
         
本博客中未标明转载的文章归作者 海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
深入解析Java中的protected修饰符 当方法或实例变量使用protected修饰符时,它们可以在同一包内的任何类中访问,并且也可以在继承它们的子类中访问。在上面的示例中,myMethod()方法和myVariable实例变量被声明为protected,因此它们可以在com.example包中的任何类中访问,以及继承MyClass的子类中访问。当父类的方法或变量使用protected修饰符时,它们可以在子类中进行访问和重写,但对于同一包中的其他类来说是不可见的。protected修饰符只允许同一包中的类访问,以及继承了它的子类访问。 阅读详情

相关推荐

java中private,public,protected详解

参照甲骨文的java文档:点击打开链接 访问级别修饰符确定其他类是否可以使用特定字段或调用特定方法。有两个级别的访问控制: 1.在顶级 - public或package-private(没有显式修饰符即默认权限)。 类可以用修饰符public声明,在这种情况下,类对所有类都可见。如果一个类没有修饰符(默认,也称为package-private),它只在自己的包中可见。 2.在成员级

Duan的博客 11万+

访问权限修饰符(public、protected、private)、封装(私有化类属性、私有化类的某些方法)

如:单例模式:单个实例,在系统中,想让某个类只能创建一个对象(如计算机电脑上的任务管理器在Windows系统下只能创建一个)(1)修饰对象:类(包括正常类和内部类)、成员变量、方法(包括构造方法和成员方法)(1)修饰对象:类(包括正常类和内部类)、成员变量、方法(包括构造方法和成员方法),必须通过类中提供的方法来实现对隐藏信息的操作(赋值)和访问(取值)(2)权限范围:被修饰对象只能在本类、同包类、不同包子类中被访问。(1)隐藏了类的某些信息,保护了类中属性的数据值。

Watermelon_Mr的博客 5292

深入解析Linux Suspend/Resume机制——从用户态到内核态的完整流程

本文深入解析Linux Suspend/Resume机制,从用户态触发到内核态执行的完整流程。详细介绍了三种挂起模式(Freeze、Standby、Suspend to RAM)的实现原理,包括系统调用入口、状态验证、设备挂起流程及平台相关操作。同时提供实战调试技巧,帮助开发者解决电源管理中的常见问题。

weixin_29313239的博客 444

详解 Java 内部类

前言 内部类在 Java 里面算是非常常见的一个功能了,在日常开发中我们肯定多多少少都用过,这里总结一下关于 Java 中内部类的相关知识点和一些使用内部类时需要注意的点。 从种类上说,内部类可以分为四类:普通内部类、静态内部类、匿名内部类、局部内部类。我们来一个个看: 普通内部类 这个是最常见的内部类之一了,其定义也很简单,在一个类里面作为类的一个字段直接定义就可以了,例: pub...

指点 6万+

物联网 Mixly-智能楼道灯

一、实验目的及要求 熟悉声音及人体红外传感器用法。 二、实验原理与内容 1.使用声音传感器实现声控灯功能。 2.使用人体红外传感器实现人体检测控制灯功能。 三、实验软硬件环境 硬件:Arduino、LED灯、声音传感器、人体红外传感器 软件:Mixly IDE 四、实验过程(实验步骤、记录、数据、分析) 核心代码截图 声控灯: 人体红外检测灯: 3.实验效果图: (1)、声控灯总线连接: (1)、声控灯声音大于一某个值时灯亮,经过2秒后灯灭: (3)、人体红外检测灯连接总线: (4)、人体红外

qq_43430810的博客 1917

R语言基础之R语言入门

R语言最初是由新西兰奥克兰大学统计系的教授Ross Ihaka和Robert Gentleman在S语言基础上开发完成的。是一门解释性语言。在我看来R语言是一门数学性极强的语言,或者说这是一门为数学而生的语言,因为其具有极其出色的计算与统计分析能力...

weixin_46912400的博客 5万+

Java 内部类详解

目录1. 静态内部类定义:访问规则:2. 非静态内部类定义:访问规则:3. 内部类使用方法外部类中使用内部类:外部类以外的地方使用内部类:4. 内部类与外部类变量同名总结 在某些情况下,一个类会放在另一个类的内部定义,这个定义在其他类内部的类就称为内部类,包含内部类的类则被称为外部类。内部类主要有几个作用: 1.内部类提供更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问 2.内部类成员可以直接访问外部类的私有数据,因为内部类相当于外部类的成员 3.匿名内部类可用于创建那些仅需一次使用的

Yaber的博客 1203

SAM3 LoRA Fine-Tuning|SAM3微调(完全对齐官方训练和配置)

本文介绍了基于官方SAM3模型使用LoRA技术进行图像目标检测与分割微调的项目。项目完全对齐官方训练配置,支持多类别高效微调,且不影响原模型的开放词汇提示能力。微调后模型在航拍图像中对道路、车辆等目标的分割效果显著提升,误检率降低。 项目提供完整的训练和推理流程: 支持双卡并行训练,显存需求大(完整微调需30G+显存) 提供训练脚本和配置文件,可灵活调整参数 包含推理可视化工具,支持与原模型效果对比,内置训练结果分析工具,可生成指标对比图 数据集采用COCO格式。

weixin_46248968的博客 359

详解Java的内部类

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class)嵌套其他类的类称为外部类(outer class)。它是我们类的第五大成员,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。①局部内部类(有类名)②匿名内部类(没有类名,重点)①成员内部类(没用static修饰)②静态内部类(使用static修饰)

weixin_69053029的博客 1004

UE5实现建筑剖切效果

UE5实现建筑剖切效果

专注GIS开发 8463

上位机 寻边器 通讯实战

寻边器通讯接口实现 本文介绍了上位机与盖泽(Gazer)和JEL品牌寻边器的通讯接口实现方案。主要内容包括: 接口定义:创建了IAlignerOperation接口,定义了获取状态、控制运动、真空吸附等核心功能。 具体实现: 盖泽寻边器(GazerAlignerCjh):通过串口通讯,实现了回零、校准、移动位置等操作 JEL寻边器(JelAligner):同样基于串口通讯,包含错误处理、状态查询等功能 工厂模式:通过AlignerFactory工厂类根据设备品牌创建对应的实现对象。 设备加载:展示了如何在系

StevenChen的博客 377

JAVA内部类详解

最近在看hystrix源码的时候,发现Netflix的牛人们,使用了大量的匿名内部类。于是又回头翻了翻《java编程思想》。书中所讲、与自己理解,记录于瓷片文章。 内部类的定义: &amp;amp;amp;nbsp;&amp;amp;amp;nbsp;&amp;amp;amp;nbsp;&amp;amp;amp;nbsp;将一个类的定义放在另一个类定义的内部,这就是内部类。 为什么需要内部类 &amp;amp;amp;nbsp;&amp;amp;a

是夜色太荒芜的专栏 969

Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知

Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知 文章目录Gitlab通过Webhook自动触发Jenkins构建任务并在更新完毕后发送钉钉消息通知1.实现思路2.新增钉钉机器人并测试消息的发送2.1.新增钉钉机器人2.2.测试发送消息到钉钉3.在Jenkins中新建一个构建任务3.1.新建任务3.2.配置任务时增加参数化构建过程3.3.配置任务添加git地址3.4.配置构建触发器生成gitlab webhook使用的token3.5.配置任务构建过程中执行的She

江晓龙的博客 3809

Java内部类-详解

文章目录一、内部类是什么?二、内部类的共性三、静态内部类和非静态内部类的区别四、四种内部类的用法1.成员内部类2.局部内部类3.匿名内部类4.静态内部类五、理解内部类六、内部类的使用场景和好处 一、内部类是什么? Java类中不仅可以定义变量和方法,还可以定义类,这样在类内部定义的类被称为内部类。内部类可以分为:静态内部类(嵌套类)和非静态内部类。非静态内部类又可以分为:成员内部类、方法内部类、匿名内部类。内部类拥有外部类的所有元素的访问权限。 二、内部类的共性 内部类仍然是一个独立的类,在编译之后内

weixin_45077810的博客 822

Cesium 相机操作

Cesium 提供了三种方式对相机的位置进行摆放。

虎康的博客 2589

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java内部类详解

目录 一、内部类的基本概念 1.1内部类的定义 1.2内部类为什么存在 二、内部类的分类和内部类对象的创建 2.1java中内部类的主要分类 2.2在使用内部类的时候创建对象 2.3在外部类内部创建内部类对象 三、内部类详解 3.1普通内部类 3.2静态内部类 3.3局部内部类 3.4匿名内部类 一、内部类的基本概念 1.1内部类的定义 可以将一个类的定义放在另...

王富贵的博客 219

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: Hadoop集群redhad离线安装Hive
下一篇: 数据清洗经验
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值