JAVA对象的进阶
封装
- 该露的露 该藏的藏
- 高内聚(类的内部数据操作 自己完成 不允许外部操作) 低耦合(仅暴露少量的方法给外部使用)
Main
package JAVA.oop.demo4;
/*
1.提高程序的安装性 保护数据
2.隐藏代码的实现细节
3.同一接口
4.提高了系统的可维护性
*/
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("林宏程");
System.out.println(s1.getName());
s1.setAge(999);//不合法的年龄
System.out.println(s1.getAge());
}
}
Student
package JAVA.oop.demo4;
//private 属性私有
public class Student {
//学习()
//睡觉()
//属性私有
private String name;//姓名
private int age;//年龄
private int id;//学号
private char sex;//性别
//提供一些可以操作这些属性的方法
//提供一些public的get set方法
//get获得这个属性
public String getName(){
return this.name;
}//alt+insert getter
//set 给这属性设置值
public void setName(String name){
this.name=name;
}//alt+insert setter
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>120||age<0){
this.age=3;
}
else {
this.age = age;
}
}
}
重载(封装使用方法同样可以重载)
Arrays.fill() 一样的方法名 有不同的使用方法
package JAVA.oop.demo4;
import java.util.Arrays;
public class Application {
public static void main(String[] args) {
int[] a={1,2,3,4};
Arrays.fill(a,0,1,2);//把数组里的0到1下标全换成2
for (int i : a) {
System.out.print(i+"\t");
}
Arrays.fill(a,0);//把数组里的数字全换成0
for (int i : a) {
System.out.print(i+"\t");
}
}
}
继承
- 继承的本质是对另一个类的抽象
- JAVA只有单继承 没有多继承 一个儿子只有一个爸爸 一个爸爸可以有多个儿子
- 在使用继承后 子类里面有一个隐藏代码 super()
object
在JAVA中 所有的类都默认直接 间接继承object类
super
代码:
main
package JAVA.oop.demo5;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test1("杨韬");
System.out.println("--------------------------");
student.test2();
}
}
Person
package JAVA.oop.demo5;
//在JAVA中 所有的类都默认直接 间接继承object类
public class Person /*extends Object*/ {
//public
//protected
//default
//private
private int money = 10_0000_0000;
protected String name = "林宏程";
public Person() {
System.out.println("Person 无参执行了");
}
//私有的无法被继承
private void say() {
System.out.println("说了一句话");
}
public void print() {
System.out.println("Person");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
Student
package JAVA.oop.demo5;
//学生 is 人
// 子类继承了父类 就会拥有父类的全部方法
//ctrl+H 查看这个类的类树的位置
public class Student extends Person {
private String name = "林涛";
public Student() {
super();//这个是隐藏代码 调用了父类的无参构造 如果父类没有无参构造 那么必须加上父类的有参构造
System.out.println("Student 无参执行了");
}
public void test1(String name) {
System.out.println(name);//杨韬
System.out.println(this.name);//林涛
System.out.println(super.name);//林宏程
}
public void print() {
System.out.println("Student");
}
public void test2() {
print();//Student
this.print();//Student
super.print(); //Person
}
}
结果
super总结
- super调用父类的构造方法 必须在构造方法的第一个
- super必须只能出现在子类的方法 或者构造方法
- super和this 不能同时调用构造方法
- 子类无论任何构造器 他都必须调用super()不去写也会隐藏生成 如果没有无参构造(父类的) 那就必须用有参构造(父类)
public Student(String name) {
super("bb");
this.name = name;
}//像是这样 这样就可以不需要父类有无参构造了
this
代表的对象不同
this:调用本身这个对象
super 代表父类对象的应用
前提
this 没有继承也可以使用
super 只能在继承条件下才可以使用
构造方法的区别
this();本类的构造
super();父类的构造
方法的重写
代码
main
package JAVA.oop.demo5;
public class Application {
public static void main(String[] args) {
//静态和非静态方法有很大区别
//静态方法 方法的调用 只和左边的类型有关
//非静态方法 可以重写
A a = new A();
a.test();//A
//父类的引用 指向了子类
B b=new A();//子类重写了父类的方法
b.test();//B
}
}
A
package JAVA.oop.demo5;
//继承
public class A extends B {
//Override 重写
@Override//注解 有功能的注释
public void test() {
System.out.println("a=>test()");
}
}
B
package JAVA.oop.demo5;
//重写都是方法的重写 和属性无关
public class B {
public void test() {
System.out.println("b=>test()");
}
}
结果
重写总结
需要有继承关系 子类重写父类方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符 范围可以扩大 不能被缩小 public>protected>default>private
- 抛出的异常 范围可以被缩小 不能被扩大 classNOTFoundException–>Exception(大)
重写 子类的方法 和父类的方法必须一致 方法体不同
重写的原因
- 父类的功能 子类不一定需要 或者不一定满足
- alt+insert ---->override 快捷键
多态
个人理解多态:因为子类的里面包括父类 所以当以父类作为类型的时候 也可以new一个子类作为引用对象 方法用的是父类里的 但是需要用到子类的时候 也可以强转为子类去使用
相当于 学生 也是 人 所以 : 人 s1=new 学生();但是这个人 不是普通的人 而是引用了学生的人
但是不可以 学生 s1 =new人 因为不是所有人都是学生
个人理解多态的意义: 在不清楚这个person到底是student还是teacher的时候 我们先定义一个person的Person类 到我们见到这个人的时候 我们再去定义他是Student类还是Teacher类个人认为这节课的目的是让我们知道多态的存在 实际使用可能是直接先给个Person类 然后在程序运行到可以判断是学生还是老师的时候 再把person强转成student或者teacher
参考这里理解 https://segmentfault.com/q/1010000018449795
注意 子类如果重写了父类的方法 那么就会用到子类的
代码
main
package JAVA.oop.demo6;
public class Application {
public static void main(String[] args) {
//一个实际对象是确定的
//new Student();
//new Student();
//可以指向引用类型就不确定了 父类的引用指向子类
//Student 能调用的方法 都是自己的 和继承父类的
Student s1 = new Student();
//Person 父类型 可以指向子类 但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s1.run();//子类重写了父类的方法 执行子类的方法
s2.run();
//对象能执行那些方法 主要对象左边的类型 和右边关系不大
s1.eat();
//Person 父类型 可以指向子类 但是不能调用子类独有的方法
//s2.eat();
((Student)s2).eat();//必须把Person类型强转成Student类型才能调用Student独有的方法eat()
}
}
Person
package JAVA.oop.demo6;
public class Person {
public void run(){
System.out.println("run");
}
}
Student
package JAVA.oop.demo6;
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
结果
多态的主要事项
- 多态是方法的多态 属性没有多态
- 父类和子类 有联系 类型转换异常 ClassCastException
- 存在条件:继承关系 方法需要重写 如果没有重写 优先执行子类的 父类引用指向子类 father f1 =new Son();
无法重写的方法
- static属于类 不属于实例
- final 常量
- private方法
instanceof
package JAVA.oop.demo6;
public class Application {
public static void main(String[] args) {
//object->String
//Object->Person->Student
//Object->Person-> Teacher
Object object = new Student();
//System.out.println(X instanceof Y);能不能编译通过
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("---------------------------");
Person person=new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编译报错
System.out.println("---------------------------");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//编译报错
//System.out.println(student instanceof String);//编译报错
}
}
多态的总结
- 父类的引用 指向子类的对象
- 把子类转换为父类 向上转型 不用强制转换 可能丢失自己本来的一些方法
- 把父类转换为子类 向下转型 需要强制转换 可以获得子类独有的方法 同时也不会丢失自己的方法
- 方便方法的调用 减少重复的代码
static的详解
static在类里的执行顺序
package JAVA.oop.demo7;
public class Person {
static {
System.out.println("静态代码块");
//静态代码块
}//1只执行一次
{
System.out.println("匿名代码块");
//代码块(匿名代码块)
}//2 赋初始值
public Person() {
System.out.println("构造方法");
}//3
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("--------------------------------------");
Person person2 = new Person();
}
}
static在类里的属性区别
package JAVA.oop.demo7;
public class Student {
private static int age;//静态的变量
private double score;//非静态的变量
public void run(){
go();
}
public static void go(){
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
// System.out.println(Student.score);
System.out.println(s1.age);
System.out.println(s1.score);
new Student().run();
Student.go();
go();
}
}
static的静态包
package JAVA.oop.demo7;
import static java.lang.Math.random;//静态导入包
import static java.lang.Math.PI;//π
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
抽象类
特点
- 不能new这个抽象类 只能靠子类去实现他 约束
- 抽象类可以写普通的方法
- 抽象方法必须在抽象类中
- 抽象的抽象
代码
抽象类
package JAVA.oop.demo8;
//abstract 抽象类 类 extends 单继承 接口可以多继承
public abstract class Action {
//约束
//abstract 抽象方法 没有方法实现
public abstract void doSomething();
public Action() {
}
}
重写抽象方法
package JAVA.oop.demo8;
//抽象类的所有方法 继承了它的子类 都必须实现他的方法 除非他的子类也是抽象类
public class A extends Action{
@Override
public void doSomething() {
}
}
抽象类的意义
抽象的意义:对代码的维护和重用。
1.因为抽象类不能实例化对象,所以必须要有子类来实现它之后才能使用。这样就可以把一些具有相同属性和方法的组件进行抽象,这样更有利于代码和程序的维护。
比如本科和研究生可以抽象成学生,他们有相同的属性和方法。这样当你对其中某个类进行修改时会受到父类的限制,这样就会提醒开发人员有些东西不能进行随意修改,这样可以对比较重要的东西进行统一的限制,也算是一种保护,对维护会有很大的帮助。
2.当又有一个具有相似的组件产生时,只需要实现该抽象类就可以获得该抽象类的那些属性和方法。
比如学校又新产生了专科生这类学生,那么专科生直接继承学生,然后对自己特有的属性和方法进行补充即可。这样对于代码的重用也是很好的体现。
所以,Java中抽象类对于代码的维护和重用有很好的帮助,也是Java面向对象的一个重要体现。
接口
普通类 只有具体的实现
抽象类 具体实现(通过子类)和规划(抽象方法)
接口 只有规范 专业的约束 约束和实现分离
接口的本质就是契约
作用
- 约束
- 定义一些方法 让不同的类实现 10----->1
- 方法都是 public abstract
- public static final
- 接口不能被实例化 接口没有构造结果
- 可以实现多个接口 implements
- 必须要重写接口中的方法
抽象类和接口区别
抽象类
就是比如我们熟悉的泰迪,哈巴,二哈,阿拉斯加,秋田犬等等大小形态有很大区别,我们怎么把他们抽象一下呢?那就是他们都有一些本质上相同的东西那就是他们都是狗,是狗就有耳朵,尾巴,四肢等等我们把这些给抽象出来,至于耳朵是啥样的,尾巴是长是短,颜色是啥,这就需要子类实现狗这个抽象方法了。
接口
接口就是一种特殊的abstract class,但是比abstract class更加抽象,
那么接口的作用是什么呢?
- Java单继承的原因所以需要曲线救国 作为继承关系的一个补充。
- 把程序模块进行固化的契约,降低偶合。把若干功能拆分出来,按照契约来进行实现和依赖。(依赖倒置原则)
- 定义接口有利于代码的规范。(接口分离原则)
abstract class 表示的是is a关系,interface表示的是like a关系。
内部类
就是在类的内部再定义一个类
这个现在可以不去了解
1.成员内部类
package JAVA.oop.demo10;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Iner iner = outer.new Iner();
iner.in();
iner.getID();
//通过这个外部类来实例化内部类
}
}
package JAVA.oop.demo10;
public class Outer {
private int id = 10;
public void out() {
System.out.println("这是外部类的方法");
}
//
class Iner {
public void in() {
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID() {
System.out.println(id);
}
}
}
//一个java类可以有多个class文件 但是只有一个public class
class A{
public static void main(String[] args) {
}
}
2.静态内部类
package JAVA.oop.demo10;
public class Outer {
private int id = 10;
public void out() {
System.out.println("这是外部类的方法");
}
static class Iner {
public void in() {
System.out.println("这是内部类的方法");
System.out.println(id);//这里是取不到id的因为 static内部类比id先加载出来 最先加载的是静态变量 然后是代码块 然后才是构造方法
}
}
}
3.局部内部类
package JAVA.oop.demo10;
public class Outer {
//局部内部类
public void method(){
class Inner{
}
}
}
4.匿名内部类
package JAVA.oop.demo10;
public class Test {
public static void main(String[] args) {
//没有名字 初始化类 不用将实例保存到变量中
new Apple().eat();
UserService userService = new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("eat");
}
}
interface UserService{
void hello();
}