1.内部类
成员内部类
1.可以使用四种访问权限修饰符修饰的
2. 局部变量是不能用static修饰的
3. 内部类字节码文件命名方式 外部类$内部类.class
4. 内部类是可以使用外部类的属性和方法的,包括私有的
5. 外部类属性和内部类属性同名的时候优先使用内部类的
6. 即使用this也是使用的内部类的,除非创建外部类对象调用
7. 使用内部类的时候必须要导包
8. 内部类创建方式 要通过 外部类对象创建内部类对象
里面包裹的类 : 内部类
外面的类: 外部类, 宿主类
四类:
成员内部类
静态内部类
局部内部类
匿名内部类
public class Car {
String color = "绿色";
private void run() {
System.out.println("跑");
}
public class 发动机{
String color = "红色的";
String type;
public void work() {
System.out.println("发动机");
run();
System.out.println(new Car().color);
}
}
}
import demo.Car.发动机;
public class Test {
public static void main(String[] args) {
Car car = new Car();
car.color = "绿色";
发动机 f = car.new 发动机();
发动机 f2 = new Car().new 发动机();
f2.type = "345";
f2.work();
}
class Test2{
public void a() {
}
}
}
2.静态内部类
1.静态内部类中可以使用静态的属性和方法
2.字节码文件的名字 外部类$内部类.class
3.静态内部类中 不能直接使用外部类的非静态的属性和方法
4内部类中的属性和外部类属性同名的时候, 可以通过外部类.静态属性 调用外部类属性
5.静态内部类可以直接创建对象 不需要外部类对象
public class Outer {
static String name;
int age;
public void run() {
System.out.println("跑");
}
static class Inner{
int a;
static int b;
static String name;
public void a() {
System.out.println("a");
System.out.println(Outer.name);
}
public static void b() {
System.out.println("static的b");
}
}
}
import demo2.Outer.Inner;
public class Test {
public static void main(String[] args) {
Inner inner = new Inner();
}
}
3.局部内部类
局部内部类 类似于一个局部变量
1.局部内部类定义在方法内部的类
2. 不能使用访问权限修饰符以及 static进行修饰
3. 局部内部类中可以使用 外部类的属性也可以使用方法中的局部变量
4. 如果局部内部类中的属性和外部类成员属性同名, 则可以使用外部类.this.属性 调用外部类的属性
5. 局部内部类只能在声明此内部类的方法中创建对象
6. 局部内部内部类只能方法被调用的时候,才能执行
public class Test {
int a = 3;
public static void main(String[] args) {
Test test = new Test();
test.test();
}
public void test() {
int age = 3;
class Inner{
public String name = "mingzi";
private int a = 5;
public void show() {
System.out.println(name);
System.out.println(age);
System.out.println(Test.this.a);
}
}
Inner inner = new Inner();
inner.show();
}
}
4.匿名内部类
1.没有自己本类的名字, 只能拿接口或者抽象类的名字代表
2.创建的是实现类或者子类的对象
左边是接口的名字 = 右边是实现类的对象 向上转型
3.不会再匿名内部类中新增 特有方法, 因为没有办法通过接口名字调用
3. 即使一个内部类或者接口 ,new了多次, 是多个实现类
4. 当有实现类或者子类只需要创建一次对象,则可以使用匿名内部类. 可以使程序结构更加简洁
5. 匿名内部类的名字 外部类$数字.class
匿名内部类中可以额外定义自己的方法, 但是一般不这样做
public class Test {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
runnable.run();
// 只想创建一个实现类的对象 , 调用一次run方法
// 利用匿名内部类的写法
Runnable runnable2 = new Runnable() {
@Override
public void run() {
System.out.println("线程2");
}
};
runnable2.run();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("线程");
}
}
public abstract class AbstractClass {
public abstract void b();
}
public class Animal implements Run{
@Override
public void run() {
System.out.println("动物跑步");
}
}
public class Person implements Run{
@Override
public void run() {
System.out.println("人跑步");
}
public void eat() {
}
}
public interface Run {
public void run();
}
public class Test3 {
public static void main(String[] args) {
Person person = new Person();
person.run();
Animal animal = new Animal();
animal.run();
Run run = new Run() {
@Override
public void run() {
System.out.println("外星人跑步");
eat();
}
public void eat() {
}
};
run.run();
//创建抽象类对象
AbstractClass class1 = new AbstractClass() {
@Override
public void b() {
System.out.println("bbb");
}
};
class1.b();
AbstractClass class2 = new AbstractClass() {
@Override
public void b() {
System.out.println("bbb");
}
};
class2.b();
}
}
基本数据类型在参数传递的时候,传递的是 数值
引用数据类型在参数传递的时候,传递的是地址(引用)
值传递 和引用传递
注意:
String字符串作为参数的时候,传递的是 地址(引用),但是常量池存储数据的特点:
如果即将要存储的数据在常量池中存在,则直接使用, 如果不存在,则重新开辟新的空间存储, 绝对不会修改内容
public class Person {
String name;
int age;
}
public class Test2 {
public static void main(String[] args) {
Person p = new Person();
p.name = "lisi";
p.age = 15;
a(p);
System.out.println("main-->"+p.name+" "+p.age);
}
public static void a(Person p) {
p.name = "zhangsan";
p.age = 5;
System.out.println("a-->"+p.name+" "+p.age);
}
}
5.异常
运行时异常
非运行时异常,编译时期就会报错,必须处理,不处理就无法运行 涉及到外界资源, 有可能会因为外界资源的改变导致 出现问题,无论是否发生异常都要求处理以后才能执行 , 在编译实际就会 提示
程序如果发生了异常
先执行try 代码块,发现异常,jvm自动的创建异常的对象 ,查找能够捕获异常的代码找catch,如果catch中的类型和异常类型匹配则执行catch块进行处理异常,程序继续向下执行,不会中断,如果catch中类型不匹配,则直接爆出异常, 让程序中断
如果没有发生异常:
先执行try块,如果没有异常则执行完try以后执行 不执行catch
finally无论是否发生异常 都会执行此代码
资源清理和关闭的操作,还有直接退出系统 才不执行 否则一定会执行 即使 return break也必须要执行
System.exit(0);不执行
throws 可以跟多个异常类型, 标明方法内部可能存在异常, 如果发生异常 将异常转给调用者,标明异常存在的可能性 抛出异常
throws 异常发生的可能性 , 声明异常 , 写在方法声明后面 , 跟的异常类型,可以跟多个,
throw产生异常,抛出异常 , 方法内部的, 跟的是异常对象, 只能跟一个,只要出现了throw 通常会结合throws 使用,throw 后面跟的是异常对象, 真正产生异常
如果想要自定义非运行时异常 继承Exception
只有继承了RuntimeException 才是运行时异常
public class LegException extends Exception{
public LegException() {
super();
}
public LegException(String message) {
super(message);
}
}
public class Test2 {
public static void main(String[] args) {
try {
a(2,"猫");
} catch (LegException e) {
// TODO: handle exception
}
System.out.println("正常运行");
}
public static void a(int leg,String animal)throws LegException {
if("猫".equals(animal) && leg ==4) {
System.out.println("猫四条腿");
}else {
System.out.println("腿数不正确");
}
}
}
public class SexException extends RuntimeException{
public SexException() {
super();
}
public SexException(String message) {
super(message);
}
}
public class Test {
public static void main(String[] args) {
try {
a("呵呵");
} catch (SexException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("正常运行");
}
public static void a(String gender) throws SexException {
if("男".equals(gender) || "女".equals(gender)) {
System.out.println("性别正常");
}else {
throw new SexException("性别超过正常范围");
}
}
}