封装的重点是对于属性
封装的意义:
-
提高程序的安全性,保护数据
-
隐藏代码的实现细节
-
统一接口
-
增加了系统的可维护性
继承
继承的本质是对某一批类的抽象
继承关键字:extends:单继承
接口可以多继承
java中类只有单继承,没有多继承
-
继承是类与类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用extends关键字来表示
私有的东西无法被继承
快捷键:Ctrl+H 看继承树
在Java中,所有的类,都默认直接或者间接继承Object类
this:本类中的属性
super:父类中的属性
类里面有默认的无参构造器
public class Person(){
public Person(){
}
}
调用对象会先走无参构造器
super注意点
-
super调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或者构造方法中
-
super和this不能同时调用构造方法
VS this
代表的对象不同:
this:本身调用这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只有在继承条件下才可以使用
构造方法:
this():本类的构造
super():父类的构造
重写:需要有继承关系,子类重写父类的方法
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符:范围可以扩大,但不能缩小
4. 抛出的异常:范围可以被缩小,但不能扩大
静态方法和非静态方法的区别很大
-
静态方法
public class B {
public static void test(){
System.out.println("B=>test()");
}
}
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
}
public class Application {
public static void main(String[] args) {
//静态方法://方法的调用只和左边,定义的数据类型有关
A a=new A();
a.test();
//父类的引用指向了子类
B b=new A();
b.test();
}
}
输出结果:A=>test() B=>test()
-
非静态方法
public class B {
public void test(){
System.out.println("B=>test()");
}
}
public class A extends B{
//Override 重写
public class Application {
//非静态:重写
public static void main(String[] args) {
//方法的调用只和左边,定义的数据类型有关
A a=new A();
a.test();
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();
}
}
输出结果:A=>test() A=>test()
子类继承了父类才能重写,重写的都是父类的方法
多态
子类重写了父类的方法,就执行子类的方法
子类没有重写父类就调用父类的,子类重写了父类的就调用子类的
//对象能执行那些方法,主要看左边的类型,和右边的关系不大
//Student 能调用的方法都是自己的或者继承父类的
Student s1=new Student();
//父类型,可以指向子类,但是不能调用子类独有的方法
Person s2=new Student();//父类的引用指向子类:通过父类去 new 子类
Object s3=new Student();
多态注意事项
-
多态是方法的多态,属性没有多态
-
父类和子类之间要有联系,否则会出现转换异常(关键字:ClassCastException)
-
存在的条件:继承关系,方法需要重写,父类引用指向子类对象
不能重写的方法
-
static 方法,属于类,不属于实例
-
final 常量
-
private 方法
instanceof:类型之间的转化:父 子
instanceof可以判断两个类之间是否存在父子关系
-
低转高不需要强制转换
-
高转低需要强制转换
-
子类转换为父类,可能丢失自己本来的一些方法
static
静态变量推荐使用类名访问
public class Student{
private static int age;//静态的变量
private double score;//非静态的变量
public static void mian(String[] args){
Student s1 = new Student();
System.out.println(Student.age);//静态变量用类名访问
}
}
static方法跟类一起加载
非静态方法可以直接访问类中的静态方法
public class Student {
private static int age;//静态的变量
private double score;//非静态的变量
public void run(){//非静态方法可以直接访问类中的静态方法
go();
}
public static void go(){
}
public static void main(String[] args) {
new Student().run();//非静态方法需要new一个对象进行访问
Student.go();//静态方法可直接访问
go();
}
}
代码块
public class Person{
//匿名代码块,在程序执行时不能主动调用。
//匿名代码块创建对象时自动创建,且在构造器之前
{
//代码块(匿名代码块):可以用来赋初始值
}
//静态代码块类一加载直接执行,永久只执行一次
static{//首先执行
//静态代码块
}
}
抽象类:abstract
抽象类的本质是一个类
抽象类的特点:
-
不能new这个抽象类,只能靠子类去实现它,就是一个约束
-
一个类里面存在了抽象方法,这个类必须声明为抽象类;抽象类里面可以写普通方法,抽象方法必须在抽象类中
-
提高开发效率,提高可扩展性
//abstract 抽象类
public abstract class Action {
//abstrsct 抽象方法,只有方法的名字,没有方法的实现
public abstract void doSomething();
}//抽象类的所有方法,继承了它的子类,都必须要实现它的方法;除非子类也是抽象类
public class A extends Action{
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口(interface):只有规范(抽象方法),约束和实现分离 。(接口就是规范,定义的是一组规则)。接口的本质是契约。接口就相当于约束。
如果要实现接口里的所有定义,必须要重写里面的所有方法
接口用interface定义,定义完之后,子类要去实现它通过implements实现,然后重写接口里的方法
接口的作用
-
约束
-
定义一些方法,让不同的人实现
-
方法都是 public abstract
-
常量都是 public static final
-
接口不能直接被实例化,因为接口中没有构造方法
-
implements 可以实现多个接口
-
必须要重写接口中的方法
//接口 关键字:interface 接口都需要有实现类
public interface userService {
//接口中定义的所有属性都是常量 public static final
int AGE=99;
//接口中定义的所有方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface timeService {
void time();
}
//抽象类 extends
//类 可以实现接口 implements 接口
//实现类一般用Impl结尾
//实现接口的类,就需要重写接口中的方法
//利用接口实现多继承
public class userServiceImpl implements userService,timeService{
内部类
内部类可以获得外部类的私有属性
静态内部类无法访问非静态的外部类属性
一个JAVA类中可以有多个class类,但是只能有一个 public class
public class Outer {
private int id=999;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
public class Application {
public static void main(String[] args) {
//外部类通过 new 实例化
Outer outer=new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
捕获和抛出异常
异常处理五个关键字: try、catch、finally、throw(手动抛出异常)、throws(方法抛出异常)
假设要捕获多个异常:从小到大
try {//try 监控区域
System.out.println(a / b);
} catch (Error e) {//catch(想要捕获的异常类型) 捕获异常
System.out.println("Error");
} catch(Exception t) {
System.out.println("Exception");
}catch(Throwable o) {
System.out.println("Throwable");
} finally{//finally 处理善后工作
System.out.println("finally");
}
快捷键 Ctrl+Alt+t
try {
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();//打印错误的栈信息
} finally {
}
主动在方法里抛出是throw,在方法上抛出是throws
public void test(int a,int b) throws ArithmeticException{
if(b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
public class Demo02 {
public static void main(String[] args) {
try {
new Demo02().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
}
}
//假设方法中处理不了这个异常,则在方法上抛出异常
public void test(int a,int b) throws ArithmeticException{
if(b==0){
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
}
用户自定义异常,只需继承Exception类即可
在程序中使用自定义异常类,大体可分为以下几个步骤
-
创建自定义异常
-
在方法中通过throw关键字抛出异常对象
-
如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理,否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
-
在出现异常方法的调用者中捕获并处理异常。
//自定义的异常类
public class myException extends Exception{
//传递的数字大于10抛出异常
private int data;
public myException(int a){
this.data=a;
}
public class test {
static void test2(int a) throws myException {
System.out.println("传递的参数为"+a);
if(a>10){
throw new myException(a);
}
System.out.println("ok");
}
public static void main(String[] args) {
try {
test2(11);
} catch (myException e) {
System.out.println("myException=>"+e);
}
}
}