1、包
java中的包和现实中的包差不多一个概念,存储java类的。
和文件系统中的文件夹非常的相似。
包的命名
一般都是域名倒着写。全部是小写字母。
在一个工程中一般都会有一个主包,比如:com.igeek
包的结构和文件系统的对比:
项目中的包:
磁盘上的目录:
导包
当我们使用我们当前类所在包以外的其他类时就需要导包。 我们使用import导包。
导包方式:
①导入整个包 import com.igeek.demo1.*; 此时这个包下所有的类都可以使用。
②导入具体的类 import com.igeek.demo1.tool; 此时只能使用这个类。(推荐的)
③静态导包 import static com… (后面再讲)
tips:处过我们自己写的类之后,有时我们需要导入jdk提供的类。比如:Scanner
JDK提供的java.lang包下的所有的类都是可以直接使用的,不需要导包,比如:String ,System ,Integer。。。
其他的包都需要导包:java.util.Scannerl;java.Util.ArrayList;等等!
2、访问修饰符
java中必须掌握的7个修饰符:public,default,protected,private,static,abstract,final
访问修饰符有4个: public(公共的) protected(受保护的) default(默认的) private(私有的).
所谓访问修饰符就是用来限制被修饰的内容的访问权限的。
访问修饰符 | 可以修饰的内容 | 访问范围 |
---|---|---|
public | 类、成员变量、成员方法、构造方法 | 所有的包中都可以访问 |
protected | 成员变量、成员方法、构造方法 | 当前类所在的包,子孙类 |
default | 类、成员变量、成员方法、构造方法 | 当前类所在的包 |
private | 类、成员变量、成员方法、构造方法 | 当前类 |
3、继承
3.1 概述
现实中的继承:继承人通过“继承”拥有类被继承人的“合法”财产。
java中的继承:子类通过“继承”拥有了父类“除过构造方法以外”其他所有成员属性和方法。
百度:
继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
3.2 继承实现
java中的继承通过 extends 实现:
父类:
package com.igeek.demo3;
/**
* @company
*
* @author
*
* 2019年8月24日上午9:38:12
*/
public class Animal {
public String name;
protected int age;
private String color = "yellow";
public void bark() {
System.out.println(color+"颜色的"+age+"岁的"+name+"---吼吼吼!!!!");
}
}
子类:
package com.igeek.demo3;
/**
* @company
*
* @author
*
* 2019年8月24日上午9:40:45
*/
public class Dog extends Animal{
}
测试:
public class Test {
public static void main(String[] args) {
Dog a1 = new Dog();
a1.age=5;
a1.name="大黄";
a1.bark();
}
}
//结果
yellow颜色的5岁的大黄---吼吼吼!!!!
dog类中并没有写任何的属性和方法,但是通过继承就自动拥有了Animal类中的age属性,name属性,[color属性],bark方法
通过上面的例子可以看出,继承可以让我们代码重用
①通过extends可以让我们的类继承任何一个非final的类,但是最多只能继承一个(单继承)。
在java中一个类永远只能直接的继承一个父类。
多继承产生的问题:
②所有的类都直接或者间接的继承了java.lang.Object类。 如果你的类不继承任何类,那么它默认就继承了Object类。所以Object类中的所有方法,每个类都有。
③两个类之间可以说通 is a 关系才能继承。(规范/道德).
Dog is a Animal。 手机是一个用电器。 。。。。。。
④子类是大于父类的。 extends:扩展。
3.3 继承的规则
①什么可以继承,什么不可以继承?
理论上除过构造方法,其他都可以继承。 关于静态方法的继承后面再说
私有的方法和属性是不能继承的???
其实私有的方法和属性是可以继承但是不能直接使用。
案例:
父类:
public class Animal {
private String name;
private int age;
public void eat() {
System.out.println(this.name+"正在吃!!");
}
}
子类:
public class Dog extends Animal{
public void lookHome() {
System.out.println(name+"正在看家");
System.out.println(getName()+"正在看家");
}
}
父类的私有属性不能直接使用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCUZJTes-1576584237189)(笔记.assets/1566613019021.png)]
如果要在子类中使用name属性,则只能使用getName()方法。
②扩展
子类继承父类之后可以扩展自己的属性和方法。
public class Dog extends Animal{
//扩展自己的属性
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//扩展自己的方法
public void lookHome() {
//System.out.println(name+"正在看家");
System.out.println(getName()+"正在看家");
}
}
这时Dog类拥有父类的属性和方法,并且拥有自己特有的属性和方法。
③构造方法
如果一个类没有显式的构造方法,编译器会默认给一个无参数的构造方法。
Animal和dog都有无参数的构造方法。
默认情况下子类会在自己构造方法的第一行调用父类的构造方法。
public Dog() {
super();//调用父类的构造方法。
}
这里的super()就是调用父类的构造方法。 super()必须写在子类构造方法的第一行。
如果父类中没有默认的构造方法,则子类也不会自动生成默认构造方法。
解决方案:在子类中添加一个有参数的构造方法。
/**
* @param name
* @param age
*/
public Dog(String name, int age) {
super(name, age);
}
④内存分析
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("旺财");
dog.eat();
dog.setColor("yellow");
dog.lookHome();
}
}
⑤类型转换
向上转型:子类转换为父类。
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog();
//将子类对象赋值给父类对象
Animal a1 = dog;
}
}
JVM要一个动物,我给他一只狗。
tips:任何需要父类的地方,子类都可以胜任。
从内存上分析:
父类对象所需要的数据,子类对象在内存中的空间中都是存在的。
当我们把Dog看做Animal时a1就只能看到animla申明的属性和方法,但是内中依然存在Dog所申明属性和方法。
向下转型:父类转换为子类。
public class Test2 {
public static void main(String[] args) {
Animal a1 = new Animal();
//父类对象赋值给子类对象需要强制类型转换
Dog d1 = (Dog)a1;
}
}
内存分析:
animal的内存空间中不具备dog需要的数据,所以转换会出异常。
java.lang.ClassCastException:
如果a1指向的就是一个dog对象就不会出异常。
public class Test3 {
public static void main(String[] args) {
Animal a1 = new Dog();
//父类对象赋值给子类对象需要强制类型转换
Dog d1 = (Dog)a1;
}
}
tips:如果将父类对象转换为子类对象,则要求,父类引用必须指向该子类对象。
4、方法重写
①概念:
所谓方法重写就是在有继承的情况下,在子类中重新定义和实现继承的父类的方法。
方法重写有时也叫方法覆盖。
案例:
父类:
public class Animal {
private String name;
private int age;
public void bark() {
System.out.println("动物在叫!!!");
}
}
子类:
public class Dog extends Animal{
//重写(覆盖)了父类的方法
public void bark() {
System.out.println("狗在汪汪汪的叫!!");
}
}
测试:
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();//狗在汪汪汪的叫!!
//子类对象赋值给父类引用
Animal a1 = dog;
a1.bark();//狗在汪汪汪的叫!!
}
}
内存分析:
②方法重写的细节
前提:继承关系
子类中的方法签名和父类一致。
肯定的:方法名必须一致。
(1)访问修饰符:
子类的方法访问修饰符的范围必须大于等于父类的方法的访问修饰符。
(2)返回值类型
子类方法中的返回值类型必须和父类一致或者是父类的方法的返回值类型的子类。
(3)参数列表
如果子类中方法的参数列表和父类中方法的参数列表不一致,则是重载了父类的方法。
参数列表必须一致才能构成重写。
③调用被覆盖的方法
被覆盖的方法可以通过super关键字调用。
super和this非常相似。
this:表示当前类对象,表示调用其他的构造方法。
super:表示父类对象,表示调用父类的构造方法(讲过)。
案例:
父类中的方法:
public void eat() {
System.out.println("动物在吃!");
}
子类中的方法:
//方法重写
public void eat() {
System.out.println("狗在吃!!!");
super.eat();//super表示父类对象。
super.bark(new A());
}
测试:
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
结果:
狗在吃!!!
动物在吃!
动物在叫!!!
5、多态
多态就是同一种形态的多种表现形式。
案例:
父类:
public class Animal {
private String name;
private int age;
public void bark() {
System.out.println("动物在叫!!!");
}
}
两个子类:
public class Cat extends Animal {
public void bark() {
System.out.println("小猫在喵喵喵的叫!");
}
}
public class Dog extends Animal{
public void bark() {
System.out.println("狗在汪汪汪的叫!!!");
}
}
测试:
public class Test {
public static void main(String[] args) {
Animal a1 = new Dog();
a1.bark();//狗在汪汪汪的叫!!!
Animal a2 = new Cat();
a2.bark();//小猫在喵喵喵的叫!
}
}
多态练习
我们设计程序,我们要遵循开闭原则:对修改关闭,对扩展开放。
两个子类:
public class Cat extends Animal {
public void bark() {
System.out.println("小猫在喵喵喵的叫!");
}
}
public class Dog extends Animal{
public void bark() {
System.out.println("狗在汪汪汪的叫!!!");
}
}
测试:
public class Test {
public static void main(String[] args) {
Animal a1 = new Dog();
a1.bark();//狗在汪汪汪的叫!!!
Animal a2 = new Cat();
a2.bark();//小猫在喵喵喵的叫!
}
}