内部类
在类的内部编写的类就叫内部类;内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类;
优点:
1、能独立继承接口,使得多继承的解决方案变得完整
2、定逻辑关系的类组织在一起,又可以对外界隐藏
3、方便编写线程代码、方便编写事件驱动程序
成员内部类
在类的内部、方法的外部编写的类就是成员内部类;
class Circle {
double radius = 0;
public Circle(double radius) {
this.radius = radius;
}
class Draw { //内部类
public void drawSahpe() {
System.out.println("drawshape");
}
}
}
特点:
以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员;如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
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成员
}
}
}
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() {
}
}
}
局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
匿名内部类
匿名内部类是在new的后面,可以用来实现一个接口或者继承一个类;不能有名称,所以没有办法引用;
格式:new 类{方法体}
静态内部类
在声明的类的时候加上static关键字,他与外部类的属性,方法是并列关系。
静态内部类就是修饰为 static 的内部类。声明为 static 的内部类,不需要内部类对象和外部类对象之间的联系,就是说,用户可以直接引用“外部类.内部类”。
重载与重写
重载
重载:在一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同
方法的返回类型和参数的名字不参与比较。即:比较时,只关注参数的类型,个数,相对位置,且返回值类型与判断是否为方法重载无关
特点:
重载Overload是一个类中多态性的一种表现;
重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序);
重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准;
重写
是指子类中定义了一个方法,这个方法的类型(返回值类型)和父类方法的类型(返回值类型)一致或者是父类的方法类型的子类型,并且这个方法的名字、参数个数、参数的类型和父类的方法完全相同。
特点:
发生在父类与子类之间;
方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同;
访问修饰符的限制一定要大于被重写方法的访问修饰符;
重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
区别
1、方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
2、重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
3、 重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
注解
注解是一种元数据,可以将它理解为注释、解释,它为我们在代码中添加信息提供了一种形式化的方法,它用于帮助我们更快捷的写代码;
一般常用的注解可以分为三类:
1、Java自带的标准注解
2、元注解,是对现有的注解进行解释说明的注解
3、自定义注解,用户可以根据自己的需求定义注解
常用的Java注解:
1、@Deprecated – 所标注内容不再被建议使用;
2、@Override – 只能标注方法,表示该方法覆盖父类中的方法;
3、@Documented --所标注内容可以出现在javadoc中;
4、@Inherited – 只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性;
5、@Retention – 只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性;
6、@Target – 只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性;
7、@SuppressWarnings – 所标注内容产生的警告,编译器会对这些警告保持静默;
8、@interface – 用于定义一个注解;
元注解:
@Retention,应用到一个注解上的时候,它解释说明了这个注解的的存活时间
@Documented,它的作用是能够将注解中的元素包含到 Javadoc 中去
@Target,指定了注解运用的地方,这个注解就被限定了运用的场景
@Inherited,继承
@Repeatable,可重复
反射
定义:反射是在运行状态时,对于任何类,都可以知道这个类的所有属性和方法(不管私有还是公共),动态调用对象的行为被称为反射机制。
特点:
-
运行状态时,任何一个类,都能知道所有的属性和方法
-
对于任何一个对象,都能调用它的方法和属性
为什么要用?
-
当遇到某个类或某个成员变量、方法的属性只对系统开发时,可以通过反射来获取;
-
在运行时判断任意一个对象所属的类、构造任意一个类的对象、调用任意一个对象的方法
-
可以获取已知名称class的内部信息
实现:
1、通过 对象名.getClass() 来获取
Student s = new Student();
Class c = s.getClass();
2、通过 类名.class来获取
Class c = Student.class;
3、Class.forName("完整的包名+类名") 来获取
Class c = Class.forName("com.gzxkb.Student");
4、获取类
asSubclass(Class<U> clazz) 把传递的类的对象转换成代表其子类的对象 Cast 把对象转换成代表类或是接口的对象
getClassLoader() 获得类的加载器
getClasses() 返回一个数组,数组中包含该类中所有公共类和接口类的对象 getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象 forName(String className) 根据类名返回类的对象
getName() 获得类的完整路径名字
newInstance() 创建类的实例
getPackage() 获得类的包
getSimpleName() 获得类的名字
getSuperclass() 获得当前类继承的父类的名字
getInterfaces() 获得当前类实现的类或是接口
getAnnotation(Class<T> annotationClass) 获取类上面的注解 isAnnotationPresent(Class<T> annotationClass) 判断是否对应的注解
5、获取类相关属性
getField(String name) 获得某个公有的属性对象
getFields() 获得所有公有的属性对象
getDeclaredField(String name) 获得某个属性对象
getDeclaredFields() 获得所有属性对象
6、获取构造函数
1、无参构造函数(必须存在无参构造函数)newInstance();
Object o = Class.forName("com.gzxkb.Student").newInstance();
2、getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
3、getDeclaredConstructors() 获得该类所有构造方法
7、步骤
获取 目标类型的Class对象
通过 Class 对象分别获取Constructor类对象、Method类对象 或者 Field 类对象
通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、法&属性的具体信息,并进行后续操作