前言:菜鸟一枚,如有问题欢迎大家在评论区指出,我们一起学习。
1.11.1:常量与枚举
在实际开发过程中,某些类型的对象是有限的几个,那么我可以考虑使用常量。在java中,我们有三种方式实现常量,这三种方式各有千秋。
第一种方式:将常量放在类中
1.使用 private 修饰构造器,使其不能被实例化和被继承
2.定义 static final 类型的成员变量,即常量
public class Constants {
public static final String APP_NAME = "MyApplication";
public static final int MAX_USERS = 100;
private Constants(){}
}
第二种方法: 接口中定义常量
接口中成员变量默认是 static final 修饰的常量
public interface Constants{
int SUCCESS = 1;
int ERROR = 2;
}
注意: 接口定义的常量虽然不可修改,但是接口允许被实例化,并且接口中不能定义静态代码块。
第三种方法:使用枚举类定义常量
1.使用 enum 关键字(jdk1.5之后)
2.定义常量类(jdk1.5之前)
jdk1.5之前的枚举类:
//jdk1.5之前的枚举类
public class Season {
//第二步:本类内部创建一组常量对象,并添加public static修饰符,对外暴露这些常量对象
public static final Season SPRING = new Season("春季");
public static final Season SUMMER = new Season("夏季");
public static final Season AUTUMN = new Season("秋季");
public static final Season WINTER = new Season("冬季");
private String info;
private Season() {
}
//第一步:私有所有的构造器(限制外部类随意创建对象并禁止继承)
private Season(String info) {
this.info = info;
}
//第三步:对外提供get方法
public String getInfo(){
return this.info
}
}
当然,我们也可以重写toString方法, 打印对象的时候,我们能直接打印对应常量的值
jdk1.5之后定义的枚举类:使用 enum 关键字
public enum Season {
//enum声明的枚举类必须在类体的第一部分给出若干本类的属性
//不同jdk1.5之前的枚举类,enum声明的枚举类省略了public static final Seanson类,构造器,因为默认值就是它,写和不写都是它
SPRING("春季"),SUMMER("夏季"),AUTUMN("秋季"),WINTER("冬季");
private String info;
//enum声明的枚举类所有的构造器默认都是私有的,并且只能使私有的,省略了private修饰,所以它不允许其他类实例化
Season() {
}
Season(String info) {
this.info = info;
}
//提供公开的get方法
public String getInfo(){
return this.name
}
@Override
public String toString() {
return this.info;
}
}
枚举类型常用方法:
1.String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!
2.String name():返回的是常量名(对象名)
3.int ordinal():返回常量的次序号,默认从0开始
4.枚举类型[] values():返回该枚举类的所有的常量对象,返回类型是当前枚举的数组类型,是一个静态方法
5.枚举类型 valueOf(String name):根据枚举常量对象名称获取枚举对象
public class TestSeason {
public static void main(String[] args) {
Season season1 = Season.SPRING;
//父类ENUM类默认重写了toString()方法
System.out.println(season1);
System.out.println(season1.name());
//发现season1有下标
System.out.println(season1.ordinal());
System.out.println("--------------------------------");
Season[] seasons = Season.values();//返回枚举类所有枚举值数组
for (int i = 0; i < seasons.length; i++) {
System.out.println(seasons[i]);
}
System.out.println("-----------------");
Season season2 = Season.valueOf("SPRING");//根据属性名返回枚举对象
System.out.println(season2);
}
}
容易混淆的点:
1.抽象类不能被实例化,但是内部有公开的构造器供子类调用
2.接口不能被实例化,并且内部没有构造器
3.枚举不能被实例化,但是内部有供自己调用的私有构造器
1.11.2:包装类
Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而当要使用只针对对象设计的API或新特性(例如泛型),那么基本数据类型的数据就需要用包装类来包装。
装箱和拆箱: 装箱,把基本数据类型转为包装类对象。拆箱:把包装类对象拆为基本数据类型。
public class Test {
public static void main(String[] args) {
//装箱:将基础类型封装为引用类型
int one = 100;
Integer integer = new Integer(one);
Integer integer1 = Integer.valueOf(one);
//拆箱:将包装类对象转为基础数据类型
int two;
two = integer1.intValue();
System.out.println(two);
//jdk1.5之后可以自动装箱和拆箱
//拆箱
int three = new Integer(one);
//装箱
Integer integer2 = one;
int four = integer2;
System.out.println(four);
}
}
注意:JDK1.5以后,可以自动装箱和拆箱。
包装类缓存对象: 数据在一定范围内,是储存在常量池中,使用常量池中数据的对象地址是一样的,可以用 == 判断,而无需 equals()方法。
Integer a = 1;
Integer b = 1;
System.out.println(a == b);//true
Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false
Integer m = new Integer(1);//新new的在堆中
Integer n = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(m == n);//false
Integer x = new Integer(1);//新new的在堆中
Integer y = new Integer(1);//另一个新new的在堆中
System.out.println(x == y);//false
1.11.3:内部类
概念:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
分类:
成员内部类:内部类定义在外部类的类体里,并且在外部类方法外面的类。
普通成员内部类(非静态成员内部类): 1.普通成员内部类只能声明普通成员 2.普通成员内部类可以访问外部类的所有成员重要:普通成员内部类,在外部类类体外创建对象,需要先创建外部类对象,再由外部类对象创建内部类对象
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();//非常容易记错
Outer.Inner inner1 = new Outer().new Inner();//另一种方式,外部类没名
静态成员内部类:static 修饰的类 1.静态成员内部类可以声明静态成员和普通成员 2.静态成员内部类不能访问外部非静态成员
重要:静态成员内部类,在外部类外创建对象时,可以直接创建内部类对象,无需先创建外部类对象
Outer.Inner2 inner2 = new Outer.Inner2();
局部内部类:内部类定义在外部类方法体里的类
有名的局部内部类:
1.不能有权限修饰符
2.局部内部类不能声明非静态成员,更像普通成员内部类,并且局部内部类只能在定义这个类的方法体里使用(随着方法的调用而创建,随着方法的结束而回收)
特殊的局部内部类------匿名内部类:匿名内部类是一种特殊的局部内部类,只不过没有名称而已。所有局部内部类的限制都适用于匿名内部类。
//一个类声明在另一个类的类体里面,就叫做内部类(在定义时各种类和方法名尽量不能重名,防止给自己造成不必要的麻烦)
public class Outer {
private int three;
private static int four;
//普通成员内部类
public class Inner {
//普通成员内部类只能声明普通成员
//普通成员内部类可以访问外部类的所有成员
private int five;
//private static int six; 错误
public void methodThree(){
}
/* public static void methodFour(){ 错误
}*/
}
//静态成员内部类
public static class Inner2 {
//静态成员内部类可以声明静态成员和普通成员
//静态成员内部类不能访问外部非静态成员
private int one;
private static int two;
public void methodThree(){
System.out.println(one);
System.out.println(two);
//发现不能访问外部类的非静态成员(虽然是普通方法,但是身处于静态内部类里)
// System.out.println(three);
System.out.println(four);
}
public static void methodFour(){
//不能访问内部类的非静态成员(静态方法)
// System.out.println(one);
System.out.println(two);
//同样不能访问外部类非静态成员
// System.out.println(three);
System.out.println(four);
}
}
public void methodOne() {
//在外部类类体里创建静态和普通内部类对象(普通方法)
Inner2 inner2 = new Inner2();
Inner inner = new Inner();
//局部内部类,没有修饰符,它不是一个成员
class Inner {
//局部内部类不能声明非静态成员,更像普通成员内部类,并且局部内部类只能在定义这个类的方法体里使用
//private static int one;
private int five;
public void methodThree(){
}
/* public static void methodFour(){
}*/
}
}
public static void methodTwo() {
//在外部类类体里创建静态内部类对象(静态方法)
Inner2 inner2 = new Inner2();
}
}
//匿名内部类有名对象
MyInterOne myInterOne2 = new MyInterOne(){
@Override
public void methodOne() {
System.out.println("再见");
}
};// 注意分号
myInterOne2.methodOne();
//匿名内部类匿名对象
new MyInterOne(){
@Override
public void methodOne() {
System.out.println("拜拜");
}
};
//匿名内部类调方法在分号前 .方法名
//匿名内部类的匿名传参
test(new MyInterOne(){
@Override
public void methodOne() {
System.out.println("幸会");
}
});
}
public static void test (MyInterOne myInterOne){
myInterOne.methodOne();
}
1.11.4:注解
三个最基本的注解:@Override @Deprecated @SuppressWarnings
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.sayHello();
//基本注解:抑制编译警告
@SuppressWarnings("unused")
int a = 100;
}
//基本注解:用于检测被修饰的方法为有效的重写方法,只能标记在方法上
@Override
public String toString() {
return "Test";
}
}
class Person {
//基本注解:标注方法已过期(过时),能用,但是不推荐
@Deprecated
public void sayHello(){
System.out.println("Hello");
}
}
Junit:回归测试框架 ,为程序员提供白盒测试,提供更多的注解。
Test注解:可以运行无参,返回类型是void的方法,选中某个方法运行,或者选择类运行其中所有 Test标注的方法 After注解:在运行Test标注的方法后运行After标注的方法 Before注解:在运行Test标注的方法前先运行Before标注的方法 AfterClass注解:类结束时运行一次 BeforeClass注解:类加载时运行一次
public class Test2 {
//BeforeClass注解:类加载时运行一次
@BeforeClass
public static void staticBefore(){
System.out.println("staticBefore");
}
//Before注解:在运行Test标注的方法前先运行Before标注的方法
@Before
public void before(){
System.out.println("before");
}
//After注解:在运行Test标注的方法后运行After标注的方法
@After
public void after(){
System.out.println("after");
}
//Test注解:可以运行无参,返回类型是void的方法,选中某个方法运行,或者选择类运行其中所有Test标注的方法
@Test
public void test(){
System.out.println("test");
}
@Test
public void test2(){
System.out.println("test2");
}
//AfterClass注解:类结束时运行一次
@AfterClass
public static void staticAfter(){
System.out.println("staticAfter");
}
}
元注解: JDK1.5在java.lang.annotation包定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。