所以内容均来自于b站“遇见狂神说”
一旦定义了一个有参构造,则必须显示的定义一个无参构造!!
package com.objectOriented.test1;
public class Student {
String name;
int age;
public Student() {//有了有参构造必须定义一个无参的
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
mac中的构造快捷键是Command+n
推荐原讲解视频:创建对象内存分析
mac的idea中查看继承关系的快捷键是ctrl+h
私有的东西无法被”直接继承“,既不能被直接访问但是可以间接的访问,比如上面通过上面的封装操作:一个方法在父类中是public修饰的,则可以在子类中直接调用;倘若是private修饰的,则不可以在子类中使用super关键字直接调用,应当通过父类中的getset方法既封装来操作!
调用父类的构造方法,必须放在子类构造器的第一行(既首先调用父类的构造方法),否则报错
public Class Person{
public Person(){
System.out.printLn("Person的无参构造执行了!")
}
}
public Class Student extends Person{
public Student(){
//super(); //这个是隐藏的,默认的可以不写,倘若要写就一定要放在第一行!!!!
System.out.printLn("Student的无参构造执行了!")
}
}
强烈建议子类一定要把无参和有参的构造写一个出来
注意,方法重写和方法重载是不一样的概念!!重写都是方法的重写,和属性无关!
重写关键字:Override
测试一:
public class A {
public static void test(){//静态方法
System.out.println("A->test");
}
}
public class B extends A{
public static void test(){//静态方法
System.out.println("B->test");
}
}
public class Application {
public static void main(String[] args) {
B b=new B();
b.test();
A a=new B();//父类的引用指向了子类
a.test();
}
}
执行结果是:
测试二:
public class A{
public void test(){ //没有static修饰
System.out.println("A->test");
}
}
public class B extends A{
@Override//重写 必须要有
public void test() {//同上
super.test();
}
}
public class Application {
public static void main(String[] args) {
B b=new B();
b.test();
A a=new B();//父类的引用指向了子类
a.test();
}
}
执行结果:
为什么上面的差距这么大,借用弹幕的话:
因为静态方法是类的方法,而非静态类是对象的方法,有static时,a调用了A类的方法,因为a是用A类定义的;没有static时,A调用的是对象的方法,而a是用B类new的,既a是B类new出来的对象,因此调用了B的方法!
至于为什么可以这样写,这是多态的内容,重写就是为了多态而生!的!
A a=new B();
另外,静态方法只能被继承,不能被重写
说到底,其本质是:a(地址)引用,指向了B类对象,所以调用的就是B类的方法
举个简单的例子,上面继承那一栏里面:
A a=new B();
既多态,父类引用子类对象!因为子类继承了父类的全部!!这样写是没有问题的!
测试一:
public class Person {
public void run(){
System.out.println("父类的run");
}
}
public class Student extends Person{}
public class Application {
public static void main(String[] args) {
Student s1=new Student();
Person p1=new Student();
s1.run();
p1.run();
}
}
运行:
很好理解,父类和子类都有run方法,父类调用子类对象的方法,由于子类的run方法继承的是父类的没有改变,所以还是父类的run方法!
测试二:子类重写父类方法
public class Person {
public void run(){
System.out.println("父类的run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("子类的run");
}
}
public class Application {
public static void main(String[] args) {
Student s1=new Student();
Person p1=new Student();
s1.run();
p1.run();
}
}
运行结果:
同上,父类调用子类的run方法,但是由于子类重写了run方法,所以执行的是子类重写后的run方法!
测试三:父类调用子类新增的方法
public class Person {
public void run(){
System.out.println("父类的run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("子类的run");
}
public void eat(){
System.out.println("子类的eat");
}
}
public class Application {
public static void main(String[] args) {
Student s1=new Student();
Person p1=new Student();
s1.run();
p1.eat();//一定会报错
}
}
这个很好理解,因为父类没有该方法!能否执行看引用类型(左),执行内容看实际类型(右)
所以,假如是Person p1=new Student()这种,在与static无关的情况下,父类要运行的方法必须要是父子两个都有的!假如子类没有重写,则父类调用的还是父类本身的方法(子类继承的是父类的没变),子类重写了则调用的是子类重写的方法!
//Student能调用的方法都是自己的或者继承父类的
Student s1=new Student();
//父类型,可以指向之类,但是不能调用子类独有的方法
Person p1=new Student();
判断两个类之间是否存在父子关系
public class Person {
public void run(){
System.out.println("父类的run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("子类的run");
}
}
public class Teacher extends Person{
@Override
public void run() {
super.run();
}
}
public class Application {
public static void main(String[] args) {
//Object->Person->Student
//Object->Person->Teacher
//Object->String
Object object=new Student();
System.out.println(object instanceof Student);
System.out.println(object instanceof Person);
System.out.println(object instanceof Object);
System.out.println(object instanceof Teacher);
System.out.println(object instanceof String);
}
}
运行:
同理:
Person person=new Student();
System.out.println(person instanceof Student);
System.out.println(person instanceof Person);
System.out.println(person instanceof Object);
System.out.println(person instanceof Teacher);
//System.out.println(person instanceof String);
运行:
首先要明白一个规矩,既java遵循”编译看左(引用类型),执行看右(实际指向类型)“的规矩,所以最后一行代码报错,既首先编译就通不过,因为Person类和String是平级,没有父子关系!第4个是false是因为编译的时候看左(Person类)和Teacher有父子关系,可行!实际执行的时候看右(Student类)和 Teacher属于同级没有关系!
同基本数据类型一样,低转高自动转换,但是高转低就需要强制了!
public class Person {
public void run(){
System.out.println("父类的run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("子类的run");
}
public void go(){
System.out.println("子类的独有的go方法");
}
}
子转父:低转高,向上转型,直接转,丢失子类中原本可以直接调用的特有方法
Student s1=new Student();
s1.go();
Person p1=s1;
//p1.go();代码报错,因为没有go方法(既会丢失子类特有的方法)
父转子:高转低,向下转型,强制转,丢失父类被子类所重写掉的方法!
Person p2=new Student();
//p2不能使用Student独有的方法,如若使用强制转换
Student s1=(Student)p2;//高转低(右转左)需要强制转换
s1.go();
//或者
((Student)p2).go();
用在方法上叫静态方法(也可以叫类方法,通过类名访问),用在属性上叫静态属性(如静态变量,也叫类变量)!
加了static关键字的,是从属于这个类的,别人用不了,只有本类能用!
public class Test1 {
{
//匿名代码块,赋初始值
System.out.println("匿名代码块!");
}
static {
//静态代码块,跟类一加载就执行,永久只执行一次!
System.out.println("静态代码块!");
}
public Test1(){
//构造器
System.out.println("构造函数!");
}
public static void main(String[] args) {
Test1 t1=new Test1();
System.out.println("=============");
Test1 t2=new Test1();
}
}
运行:
同样的,一个类被final修饰了就不能被继承了,称之为断子绝孙修饰符
//interface 定义的关键字 接口都需要有实现类
public interface UserService {
//接口中的属性默认都是静态常量,既public static final
int AGE=10;
//接口中的所有定义默认都是抽象的public,既定义的时候public abstract可以不用写
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
//类只能单继承,而接口可以多继承,且必须重新接口里面的方法
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {}
@Override
public void timer() {}
@Override
public void delete(String name) {}
@Override
public void update(String name) {}
@Override
public void query(String name) {}
}
总结:
所谓内部类就是在一个类的内部再定义一个类,比如A类中定义一个B类,则B类称之为A类的内部类,A类称之为B类的外部类!
public class Outer {
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer=new Outer();
//内部类的创建格式
Outer.Inner inner=outer.new Inner();
inner.in();
}
}
运行:
那么内部类能干嘛呢,我们通过内部类可以获得外部类的私有属性和方法
public class Outer {
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
public void getId(){
//System.out.println(id);会报错
}
}
}
上面会报错的原因是因为:按照我们之前在static总结的来分析,类的执行(加载)顺序是静态->匿名->构造函数!所以,假如上面的的代码要想通过,得把id也用static修饰才可以!
public class Outer{
//局部内部类
public void method(){
class Inner2{
public void in(){}
}
}
}
需要说明的是,一个java文件里面只能有一个public class,但是却可以有多个class,既:
public class A{}
//public class A{} 错误
class C{}
class D{}
......
public class test {
public static void main(String[] args) {
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("吃了苹果");
}
}
运行:
你甚至还可以在下面写上一个接口,当然这个就不做描述了!
三种异常:
public class Exception1 {
public static void main(String[] args) {
int a=10;
int b= 0;
System.out.println(a/b);
}
}
如何捕获这异常呢?-----------使用try/catch语句
public class Exception1 {
public static void main(String[] args) {
int a=10;
int b= 0;
try {//try表示监控区域(有问题转到catch)
System.out.println(a/b);
}catch (ArithmeticException e){//catch为捕获异常
System.out.println("算术运行异常!");
}finally {//处理善后工作
System.out.println("over");
}
//finally可以不要,但是像涉及到IO,资源的关闭可以放到finally里!
}
}
另外,try/catch也可以像if/else一样可以有多个catch:
public class Exception2 {
public static void main(String[] args) {
try {
new Exception2().a();
}catch (Error e){
System.out.println("Error");
}catch (Exception e){
System.out.println("Exception");
}catch (Throwable e){
System.out.println("Throwable");
}finally {
System.out.println("over");
}
}
public void a(){
b();
}
public void b(){
a();
}
}
注意,异常等级越高的一定要放在后面!根据先后执行的顺序,满足了就不会执行后面的语句了!
不知道是什么异常可以这样写:
try{
.....
}catch(Exception e){
e.printStackTrace();//打印出具体的异常信息!
}
异常的抛出
public class Exception3 {
public static void main(String[] args) {
try{
new Exception3().test(3,0);
}catch (ArithmeticException e) {
e.printStackTrace();
}
}
//假设这个方法中处理不了这个异常,则可以主动抛出异常,让更高级别的去处理
public void test(int a,int b){
if(b==0){
throw new ArithmeticException();
} else{
System.out.println(a/b);
}
}
}
//自定义一个异常类,要继承Exception
public class MyException extends Exception{
private int detail;
public MyException(int a){
this.detail=a;
}
//toString:异常的打印信息
@Override
public String toString() {
return "MyException{"+detail+"}";
}
}
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {//注意,这里是throws不是throw
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);//处理为要么这里try/catch,要么抛出去
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
}catch (MyException e){
//e.printStackTrace();
System.out.println("MyException>>"+e);//e即为执行toString()
}
}
}
原文:https://www.cnblogs.com/zhiaiyaner/p/14999108.html