内部类
成员内部类
成员内部类就是定义在一个类的内部,其实是相当于成员变量的位置。
下面这两种其实都可以被称为成员内部类的,只不过一般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来进行很方便的传参,
主函数里面对参数进行遍历
但是其实不知道这样进行传参的具体意义所在。
自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。
希望得到指点。