java内部类以及为什么要用public static void修饰main()函数,String args[]是什么?(浅显的一些探索)

简介: 内部类成员内部类成员内部类就是定义在一个类的内部,其实是相当于成员变量的位置。下面这两种其实都可以被称为成员内部类的,只不过一般static修饰的这种我们一般也可以称之为静态内部类。我们先来研究成员内部类(也可以称之为非静态内部类)怎么定义的话合理即可,明白意思就可以了。

内部类


成员内部类


成员内部类就是定义在一个类的内部,其实是相当于成员变量的位置。


下面这两种其实都可以被称为成员内部类的,只不过一般static修饰的这种我们一般也可以称之为静态内部类。我们先来研究成员内部类(也可以称之为非静态内部类)怎么定义的话合理即可,明白意思就可以了。


class Outer{
  class Inner{
  //非静态成员内部类
    }
    static class Inner_1
    {
  //静态成员内部类
    }
  public static void main(String args[]){
  /*.........*/
  }
  }


来看一个简单的例子,也可以自己去测试访问和定义的修饰符


package java_practice;
public class OuterandInner {
    private byte b = 1;
    static String country = "china";
    String home = "shanxi";
    public void systemdemo() {
//        System.out.println(Inner.this.name);//这样是不可以的。
    }
    public String author = "jgdabc";
    class Inner {
        String name = "jgdabc";
        //        static String name_1 = "";//这样不允许
        private String password = ".....";
        public void systemdemo() {
            System.out.println(OuterandInner.this.author);
            System.out.println(author);
            System.out.println(Inner_1.age);
//            System.out.println(name_1);//这样访问不了
            System.out.println(b);//非静态内部类可以访问到外部私有化成员
        }
    }
    static class Inner_1 {
        public static void showdemo() {
            //.....
//            System.out.println(Inner.name);//这样不可以
//            Inner inner = new Inner();//不可以这样去new,因为没有main方法
//            System.out.println(b);//静态局部内部类是不能访问到外部类私有成员的
            System.out.println(country);
        }
        String name_1 = "jgdabc_1";
        private String password_1 = "lmddkskk";
        static int age = 19;
        public void systemdemo() {
//            System.out.println(OuterandInner.this.author);//这样是不可以的
            System.out.println(OuterandInner.country);//这样可以访问,并且直接通过类名进行访问
        }
    }
    public static void main(String args[]) {
        System.out.println("......");
        OuterandInner outerandInner = new OuterandInner();
//        System.out.println(outerandInner.name);//访问不到内部类成员
//        System.out.println(name);//
        System.out.println(outerandInner.author);//自己的成员变量直接可以通过实例访问
        Inner inner = outerandInner.new Inner();
        System.out.println(inner.name + inner.password);
//        Inner inner1 = new Inner();//动态的外部类不能被直接在外部类new()
//        System.out.println(name_1);//不能访问
        OuterandInner outerandInner1 = new OuterandInner();
//        System.out.println(outerandInner1.name);//不能访问
        Inner_1 inner_1 = new Inner_1();//静态的可以直接进行new实例化
        System.out.println(inner_1.name_1 + inner_1.password_1);
        System.out.println(Inner_1.age);//直接通过类名来调用静态成员内部类的静态成员
//        System.out.println(Inner_1.name);//这样是不可以的
        Inner_1.showdemo();//也可以直接通过类名调用静态成员内部类的静态方法。
    }
}


上面代码测试了一些常规的方法。下面简单说明几点


1:首先非静态成员内部类里面是不可以定义静态的属性的,否则编译不会通过。


2:非静态成员内部类成员不能被外部直接访问,不能只通过实例外部类访问内部类成员


3:访问非静态成员内部类成员属性可以通过外部类实例的对象.new 内部类,

示例如下


// An highlighted block
        Inner inner = outerandInner.new Inner();


4:非静态成员内部类可以访问到外部类的属性

然后可以通过inner调用非静态成员内部类属性。


5:非静态成员内部类可以访问到外部私有化属性。


6:外部类也是不能直接访问静态局部成员内部类成员的,这个特点同属于对内部类访问的特点。


7:静态成员内部类可以直接自己进行实例化,而无需通过外部类实例进行调用实例化。


8:静态成员内部类不可以访问到外部类的私有化成员


9:静态成员内部类可以直接访问到外部类的静态成员


10:静态成员内部类不能直接访问外部类非静态成员


局部内部类


局部内部类是一个在方法中定义的内部类


既然是局部内部类,定义在方法体中,那么只在当前方法体当中有效。无论是静态的还是非静态的,都是一样的法则。


特别注意它的作用范围,就是是去实例化它所在的类,只要不再方法体内都是无效。


public void systemdemo() {
        class demo_test {
            int age = 19;
            public int id = 123;
//          static String name= "hello";//不可以有静态修饰的成员
//            static void system_demo()
//            {
//                //不可以这样用
//            }
            private String password = "";
            public void show_demo() {
                System.out.println("我是局部内部类");
                   System.out.println(home+b+password);//可以访问到外部类的成员,即便是私有的。
            }
        }
        demo_test demo_test = new demo_test();
        demo_test.show_demo();
//        System.out.println(Inner.this.name);//这样是不可以的。
    }
//    new demo_test();//这样是不可以的


没有静态局部内部类一说



匿名内部类


匿名内部类也是经常会用到,就比如在重写一个比较器的时候可以通过类名内部类实现。另外,我们也可以自己定义一些具备功能的接口去实现匿名内部类。


简单举例说明一下


package java_practice;
class demo{
    public void demo()
    {
        System.out.println("demo");
    }
}
public class AnonymousInner {
    public static void main(String args[])
    {
        new demo(){
            public void demo()
            {
                System.out.println("demo重写");
            }
        }.demo();
    }
}



下面这个例子实现了内名进行重写比较器


package java_practice;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo01 {
    public static void main(String args[])
    {
        TreeMap tm = new TreeMap<String,String>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //。。。
            }
        });
        tm.put("Hello","world");
        String  set = String.valueOf(tm.keySet());
        System.out.println(set);
        System.out.println(set.getClass());
        System.out.println(set);
    }
}


package java_practice;
public class Student implements Comparable<Student>{
    private int age;
    private String name;
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    @Override
    public int compareTo(Student s) {
        int num = this.age - s.age;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }
}


package java_practice;
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo1 {
    public static void main(String args[]) {
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
        Student s1 = new Student(29, "西施");
        Student s2 = new Student(28, "王昭君");
        Student s3 = new Student(30, "貂蝉");
        Student s4 = new Student(33, "杨玉环");
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        for (Student s : ts) {
            System.out.println(s.getName() + "" + s.getAge());
        }
    }
}


匿名内部类实现接口


先给一个不适用匿名内部类实现的例子


package java_practice;
interface Demo_{
    void demo_d();
}
class Demo_im implements Demo_
{
    @Override
    public void demo_d() {
        System.out.println("实现demo_");
    }
}
public class Demo_de {
    public static void main(String args[])
    {
        Demo_im demo_im = new Demo_im();
        demo_im.demo_d();
    }
}


package java_practice;
interface Demo_{
    void demo_d();
}
public class Demo_de {
    public static void main(String args[])
    {
        Demo_ demo= new Demo_(){
            @Override
            public void demo_d() {
                System.out.println("匿名实现接口");
            }
        };
        demo.demo_d();
    }
}



main方法的一些疑问


为什么main方法要用static修饰


我就疑惑为什么mian方法非要是静态的?

我的理解比较浅显。因为这样的设计一定经过很好的预先思考的。对java的底层理解不是很深入。所以自己去参考了一些说法。


首先我们自己从程序执行上面去理解。我们的main方法是在类中,在类中的方法的一个特点就是如果如果不用static修饰,那就必须用实例化才可以访问,但是main是作为程序的如果啊!我们如果不进行直接访问的话,就得自己去实例化main,这样就比较复杂了。所以用static修饰得话,对我们得使用带来了一定得不变。这样其实这样修饰类成为了一种约定。


static修饰方法得特点再说明一下。



也就是说,static 修饰的方法陈为静态方法,静态方法是不依赖类的实列的,不需要通过类的实例去调用。main方法的调用是通过类的加载,链接,以及初始化,main没有被实例化过,所以需要调用的只能是通过声明为静态,然后进行调用。


为什么需要public 修饰符?

这个就比较简单了。我们的java程序需要靠java虚拟机来调用,我们的这种执行调用方式属于外部调用,如果没有public修饰,是无法实现调用的,程序也就无法执行。


为什么需要void修饰?

还是从程序执行需要方面来看,如果没有void修饰是一定需要返回值的。返回值对main又有什么意义呢?我们程序从main函数进行输出就是为了输出程序执行的内容。没有必要去返回值,返回又给谁呢?这不是我们需要的。


对比c,c++,的话,我们就好奇,为什么c,c++就可以进行返回,int main(),执行机制不一样啊,c,c++在程序进入函数执行的是偶,会启动运行时库,然后初始化环境,启动入口函数,然后程序进行执行,执行完毕后,退回运行时库,退回操作系统,然后操作系统继续调度其它的程序。


==但是java就不一样了。我们的java是由jvm进行调度的,jvm调度main函数,jvm被设计为不接受任何返回值,所以也就不能进行返回。

自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。


为什么main方法里面的参数是(String[] args)(一个字符串数组?)

String[] args[]或者String args[] 这样都是没有问题的,这个字符串主要的作用就是运行main函数的输入参数,不然它也不会写在那里,我们给main传入参数,args这个数组就会进行接收。


具体是如何传入呢?

可以利用idea来进行很方便的传参,



主函数里面对参数进行遍历



但是其实不知道这样进行传参的具体意义所在。


自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。

希望得到指点。


相关文章
|
1月前
|
Java 编译器
Java“返回类型为 void 的方法不能返回一个值”解决
在 Java 中,如果一个方法的返回类型被声明为 void,那么该方法不应该包含返回值的语句。如果尝试从这样的方法中返回一个值,编译器将报错。解决办法是移除返回值语句或更改方法的返回类型。
|
1月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
25 1
|
2月前
|
Java
java基础(11)函数重载以及函数递归求和
Java支持函数重载,即在同一个类中可以声明多个同名方法,只要它们的参数类型和个数不同。函数重载与修饰符、返回值无关,但与参数的类型、个数、顺序有关。此外,文中还展示了如何使用递归方法`sum`来计算两个数之间的和,递归的终止条件是当第一个参数大于第二个参数时。
32 1
java基础(11)函数重载以及函数递归求和
|
1月前
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
22 3
|
3月前
|
存储 运维 Java
函数计算产品使用问题之怎么配置定时触发器来调用Java函数
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
存储 Java 数据库
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(中)
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(中)
63 1
|
Java 编译器
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(上)
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(上)
63 1
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(上)
|
存储 Java 编译器
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(下)
Java-对象的操作(构造、初始化、封装)、static成员以及代码块(下)
52 0
|
存储 Java 编译器
【Java SE】static成员及代码块
【Java SE】static成员及代码块
【Java SE】static成员及代码块
|
存储 Java
Java之static成员与代码块
本篇文章主要介绍JavaSE中一些不是很常见的知识点,但也会涉及,需要了解一下
120 0
Java之static成员与代码块