JavaSE学习之内部类及常用API
这篇文章主要介绍了JavaSE中的内部类和几个常用的API,文中的示例代码介绍详细,对我们学习JavaSEI有一定的帮助,感兴趣的小伙伴可以跟随小编一起学习一下
目录
1.内部类
1.1 内部类概述
1.2 成员内部类
1.3 局部内部类
1.4 匿名内部类
1.5 匿名内部类在开发中的使用
2.常用API
2.1Math
2.2 System
2.3 Object
2.4 Array的排序
1.内部类
1.1 内部类概述
内部类:就是在一个类中定义一个类。例如:在一个类A内部定义一个类B,类B就被称为内部类
格式:public class 类名{修饰符 class 类名{}}
范例
1 2 3 4 | public class Outer{ public class Inter{ //内部类 } } |
内部类的访问特点
1. 内部类可以直接访问外部类成员,包括私有
2. 外部类如果想访问内部类就要创建对象
举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Outer { //创建外部类 private int age= 9 ; public class Inter{ //创建内部类 //内部类创建方法 public void show(){ //内部类可直接访问外部类 System.out.println(age); } } public void method(){ //这里是外部类的调用,那么不能直接像下面一样调用show()方法, //不然就会报错,不能直接访问 //show();不能这样 //应改为创建内部类对象,通过对象进行访问 Inter i= new Inter(); i.show(); } } |
1.2 成员内部类
按照内部类在类中的位置不同,可以分为两种形式
在类的成员位置:成员内部类
在类的局部位置:局部内部类
1 2 3 4 5 6 7 8 9 10 11 | //类 public class Outer { //创建外部类 private int age= 9 ; public class Inter{ //创建内部类 //内部类创建方法 public void show(){ //内部类可直接访问外部类 System.out.println(age); } } } |
1 | //测试类 |
那么怎么不让它报错呢?如何创建呢
外部类.内部类 对象名=new 外部类.new内部类();
Outer.Inter oi=new Outer().new Inter();
1 2 3 4 5 6 7 | //测试类 public class Main { public static void main(String[] args) { Outer.Inter oi= new Outer(). new Inter(); //构造内部类对象 oi.show(); } } |
但是,一般情况下,为了安全性不会将内部类定义为公有,会设置为私有,上面的Outer.Inter oi=new Outer().new Inter();
就不能这样构造内部类的对象了,否则就会报错,那么该如何创建呢?
很简单,因为外部类可以通过创建内部类的对象进行访问内部类,那么就可以在测试类中写外部类的方法,从而进行间接访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //类 public class Outer { //创建外部类 private int age= 9 ; private class Inter{ //创建内部私有类 //内部类创建方法 public void show(){ //内部类可直接访问外部类 System.out.println(age); } } public void method(){ Inter i= new Inter(); //创建内部类对象间接访问 i.show(); //调用方法 } } |
这样就可以输出内部类的值了
运行结果
9
1.3 局部内部类
局部内部类是在方法中定义的类,所以外界是无法访问的,需要在方法内部创建对象并使用该类可以直接访问外部类的成员,也可以访问方法内部的局部变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //类 public class Outer { //创建外部类 private int age = 9 ; public void method() { //在方法中局部创建内部类 class Inter { //创建内部类 private int age2 = 2 ; //局部变量也可以 public void show() { System.out.println(age); System.out.println(age2); } } Inter i = new Inter(); //创建内部类对象间接访问 i.show(); //调用方法 } } |
1 2 3 4 5 6 | public class Main { public static void main(String[] args) { Outer o= new Outer(); o.method(); //间接调用方法 } } |
1.4 匿名内部类
前提:存在一个类或者接口,这里的类可以是具体类,也可以是抽象类
格式:
new 类名或者接口名(){重写方法}
范例:
new Inter(){public void show(){}};
解释: new Inter()是匿对象,继承了这个类,或实现了这个接口
本质: 是一个继承了该类或者实现了该接口的子类匿名对象,
匿名内部类是局部内部类的一种形式,写的时候也应该在方法中
1 2 3 4 | //前提:一个类或者接口 public interface Inter { //写接口 void show(); //写抽象方法 } |
那么既然是对象,就可以通过对象调用方法
1 2 3 4 5 6 7 8 9 10 11 | public class Outer { //创建外部类 public void method() { new Inter() { //这个是对象 @Override //重写方法 public void show() { System.out.println( "匿名内部类" ); } }.show(); //通过对象调用方法 } } |
这块是重点:new Inter() {//这个是对象 @Override//重写方法 public void show() { System.out.println("匿名内部类"); } }.show();//通过对象调用方法,这里采用了对象调用方法,上面整体是对象,然后.show()
调用方法
1 2 3 4 5 6 7 | //测试类 public class Main { public static void main(String[] args) { Outer o= new Outer(); o.method(); //调用方法 } } |
接下来,有个疑问,你会说,如果我想多次调用方法,是不是要写很多次这个方法呢?答案是否定的,既然是内部类,那么就可以通过多态形式进行,即:Inter i=new Inter(){};
然后通过i来调用show()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Outer { //创建外部类 public void method() { Inter i = new Inter() { //多态形式,左面接口名,右面对象 @Override //重写方法 public void show() { System.out.println( "匿名内部类" ); } }; i.show(); //遵循编译看左面,执行看右面 i.show(); } } |
1.5 匿名内部类在开发中的使用
学完了匿名内部类之后,那么它在开发中有哪些运用呢?
在开发时,如果要实现一个接口方法时,不需要再创建类,比如之前写的猫跳高了,如果想写狗跳高了还要重建一个类,这样显得太过于繁琐,而且占用空间,既然内部类本质是类的对象,那么直接使用就会大量降低代码的低效性
1 2 3 4 | //接口 public interface Jummping { void jump(); //抽象类 } |
1 2 3 4 5 | //操作类 public class JumppingOperator { public void useOperator(Jummping j){ //接口名作为形参,new Jumpping(){} j.jump(); //内部类对象调用方法 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class Jumpping { public static void main(String[] args) { JumppingOperator j = new JumppingOperator(); //创建操作类对象 j.useOperator( new Jummping() { @Override public void jump() { System.out.println( "猫跳高了" ); } }); //用匿名内部类实现 //重复使用,就不用再创建Cat类或者Dog类了 j.useOperator( new Jummping() { @Override public void jump() { System.out.println( "狗跳墙了" ); } }); } } |
2.常用API
2.1Math
public final class Math extends Object被final修饰,是最终类,详细内容见APi手册
通过帮助文档知道,它没有构造方法,那么如何使用类中的成员呢?
这时候就需要看成员是否都是静态的,如果是,通过类名就可以直接调用
常用方法
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 | public class Main { public static void main(String[] args) { //绝对值 System.out.println(Math.abs(- 88 )); System.out.println(Math.abs( 88 )); System.out.println( "----------" ); //返回大于或者等于参数的double值为一个整数,(向上取整) System.out.println(Math.ceil( 1.12 )); System.out.println( "----------" ); //返回0小于或者等于参数的double值为一个整数,(向下取整) System.out.println(Math.floor( 1.21 )); System.out.println( "----------" ); //返回最大值 System.out.println(Math.max( 1 , 2 )); System.out.println( "----------" ); //返回最小值 System.out.println(Math.min( 2 , 6 )); System.out.println( "----------" ); //返回a的b次幂 System.out.println(Math.pow( 2 , 2 )); System.out.println( "----------" ); //返回四舍五入的整数值 System.out.println(Math.round( 1.51 )); System.out.println( "---------" ); //返回随机值,[0-1.0) System.out.println(Math.random()); //返回1-100整数随机值 System.out.println(( int )(Math.random()* 100 )+ 1 ); } }<font face= "Arial, Verdana, sans-serif" ><span style= "white-space: normal;" > </span></font> |
运行结果
88
88
----------
2.0
----------
1.0
----------
2
----------
2
----------
4.0
----------
2
---------
0.6041376042702374
78
2.2 System
不能实例化,不能创建对象,静态修饰
常用方法
1 2 3 4 5 6 7 8 9 | public class Main { public static void main(String[] args) { System.out.println( "start" ); System.exit( 0 ); //java虚拟机已经停止运行,无法在进行执下面的语句 System.out.println( "end" ); } } <font face= "Arial, Verdana, sans-serif" ><span style= "white-space: normal;" > </span></font> |
运行结果
start
1 2 3 4 5 6 7 8 9 10 11 12 | public class Main { public static void main(String[] args) { System.out.println(System.currentTimeMillis()* 1.0 / 1000 / 60 / 60 / 24 / 365 + "年" ); System.out.println( "开始计算下面程序执行的时间" ); long start=System.currentTimeMillis(); //用lang定义,因为数字太大 for ( int i = 0 ; i < 10000 ;i++){ System.out.println(i); } long end=System.currentTimeMillis(); //用lang定义 System.out.println( "程序运行时间为:" +(end-start)+ "毫秒" ); } } |
2.3 Object
概述
Object是类层次结构的根,每个类都可以将Object作为超类。所有类都直接或者间接的继承自该类
构造方法: public Object()
回想面向对象中,为什么说子类的构造方法默认访问的是父类的无参构造方法?
因为它们的顶级父类只有无参构造方法心
toString()方法的使用
可以使得单独的多个属性变得有联系,让人一眼就能够看明白什么意思,例如我们在前面讲到的创建学生实体类时,在测试类输出时还要用getXxx()+setXxx
才能进行输出,有了这种方法,我们就可直接进行使用了,这个方法建议所有子类进行重写使用,在使用时可以直接使用方法,快捷键还是Alt+Inster
下面可以看到toString()方法
下面进行举例:
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 | public class Student { //其实这里继承了Object,所以Student这个类理论上是子类, //所以可以使用toString()方法,但要重写 private String name; private int age; public Student() { } public Student(String name, int age) { this .name = name; this .age = age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public String toString() { //重写方法 return "Student{" + "name='" + name + '\ '' + ", age=" + age + '}' ; } } |
1 2 3 4 5 6 7 8 9 | //测试类 public class Main { public static void main(String[] args) { Student s= new Student( "张三" , 18 ); //采用有参构造 System.out.println(s); //因为使用了toString()方法, // 就不用再用getName(),getAge()输出了,直接输出s } }<font face= "Arial, Verdana, sans-serif" ><span style= "white-space: normal;" > </span></font> |
运行结果
Student{name='张三', age=18}
这样就可以让他们之间建立一种联系
equal()方法
比较的是内容值,当然,如果按照上面的方法进行比较姓名,年龄,它返回的的地址,因为地址不同,那么就会返回false,这个还需要在子类中重写方法,快捷键依然是那个
然后一直点下一步
再删掉这部分即可
1 2 3 4 5 6 7 8 9 10 11 12 | //测试类 public class Main { public static void main(String[] args) { Student s1= new Student( "张三" , 18 ); //采用有参构造 System.out.println(s1); Student s2= new Student( "张三" , 18 ); //采用有参构造 System.out.println(s2); System.out.println(s1.equals(s2)); //这里因为是new出来的,所以比较地址就会返回false,那么只有重写了方法才会 } } |
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 | //学生类 public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this .name = name; this .age = age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public boolean equals(Object o) { if ( this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Student student = (Student) o; if (age != student.age) return false ; return name != null ? name.equals(student.name) : student.name == null ; } } |
这是对equals()方法代码内容的解释
2.4 Array的排序
对于封装好的排序方法,不用岂不是太可惜,但是用之前我们也要思考自己能否写出一个高效的算法排序的方法。
下面进行介绍Arrays类的使用,由于APi中方法太多,详细内容还请到API中自行查看,这里讲述两种常用的方法:
工具类的设计思想:
1. 构造方法用private修饰:为了防止外界创建对象
2. 成员用public static修饰:使用类名来访问该成员变量
1 2 3 4 5 6 7 8 9 10 11 | import java.util.Arrays; public class Main { public static void main(String[] args) { int []arr={ 2 , 7 , 3 , 4 , 9 , 5 }; System.out.println( "排序前: " +Arrays.toString(arr)); Arrays.sort(arr); System.out.println( "排序后: " +Arrays.toString(arr)); } }<font face= "Arial, Verdana, sans-serif" ><span style= "white-space: normal;" > </span></font> |
运行结果:
排序前: [2, 7, 3, 4, 9, 5]
排序后: [2, 3, 4, 5, 7, 9]
现要求从键盘录入数字,要求数组是动态的,对数据进行排序
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Main { public static void main(String[] args) { Scanner sc= new Scanner(System.in); System.out.println( "请你输入一个数n:" ); int []arr= new int [sc.nextInt()]; //动态数组 for ( int i= 0 ;i< arr.length; i++){ arr[i]=sc.nextInt(); } Arrays.sort(arr); System.out.println( "排序后:" +Arrays.toString(arr)); } }<font face= "Arial, Verdana, sans-serif" ><span style= "white-space: normal;" > </span></font> |
录入:
5
1 5 3 7 9
运行结果:
[1, 3, 5, 7, 9]
以上就是JavaSE学习之内部类及常用API的详细内容
原文链接:https://blog.csdn.net/weixin_52924633/article/details/121861079