目录
1.访问限定符
范围 | private | 默认 | protected | public | |
1 | 同一个包中的同一个类 | Yes | Yes | Yes | Yes |
2 | 同一个包中的不同类 | Yes | Yes | Yes | |
3 | 不同包中的子类 | Yes | Yes | ||
4 | 不同包中的非子类 | Yes |
注意:修饰符可以用来修饰类中的属性,成员方法以及类(类只能用默认和public修饰)
2.包
1.概念:
2.命名规则:
3. 常见的包
java中只能导入某个包下的某个具体的类
3.封装(encapsulation):
1.概念:
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口(方法)来和对象进行交互
2.封装实现步骤
1.属性私有化(private)
2.提供(public)set方法,用于对属性判断并修改
3.(public)get方法用于获取属性的值
【封装例题】
创建程序,在其中定义两个类:Account和AccountTest类体会Java的封装性。
1. Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)
2.密码(必须是六位),如果不满足,则给出提示信息,并给默认值
3.通过setXxx的方法给Account 的属性赋值。
4.在AccountTest中测试
package practice_1_16;
import java.util.Scanner;
public class AccountTest{
public static void main(String[] args) {
Account test = new Account("王聪",10,"1234567");
// test.setName("王聪");
// test.setBalance(10);
// test.setPassword("1234567");
test.info();
}
}
class Account{
private String name;
private int balance;
private String password;
public Account() {
}
public Account(String name, int balance, String password) {
this.setName(name);
this.setBalance(balance);
this.setPassword(password);
}
public String getName() {
return name;
}
public void setName(String name) {
if(name.length() >= 2 && name.length() <= 4){
this.name = name;
}else{
System.out.println("名字长度不符合规范,默认为空");
this.name = null;
}
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
if(balance <= 20){
System.out.println("余额小于20,不符合规范");
return;
}else{
this.balance = balance;
}
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
if(password.length() != 6){
System.out.println("密码长度不符合要求,默认初始密码123456");
this.password = "123456";
}else {
this.password = password;
}
}
public void info(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入密码查看:");
String password = sc.nextLine();
if(password.equals(this.password)){
System.out.println("密码输入正确");
System.out.println("姓名="+this.name+"余额="+this.balance+"密码="+this.password);
}else {
System.out.println("密码输入错误,您没有权限查看");
}
}
}
4.继承
1 继承的语法
修饰符 class 子类 extends 父类 {//...}
2.继承细节
1.通过子类对象访问成员时,遵循就近原则(若在父类中找到的属性是private修饰,则直接报错)
public class Student {
public String name;
public int age;
private double score;
//无参构造器
// public Student() {
// }
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
public void setScore(double score){
this.score = score;
}
public void info(){
System.out.println("姓名="+this.name+"\t"+"年龄="+this.age+"\t"+"成绩="+this.score);
}
}
子类Pupil
public class Pupil extends Student{
public Pupil() {
super("xiaojinli",8,90);
}
public void testing(){
System.out.println("小学生"+name+"正在考小学数学");
}
}
子类Graduate
public class Graduate extends Student{
public Graduate() {
super( "锦鲤",18,100);
}
public void testing(){
System.out.println("大学生"+name+"正在考高等数学");
}
}
测试类test01
public class test01 {
public static void main(String[] args) {
Pupil pupil = new Pupil();
pupil.name = "小锦鲤";
pupil.age = 6;
pupil.setScore(60);
pupil.testing();
pupil.info();
Graduate graduate = new Graduate();
graduate.name = "锦鲤呀";
graduate.age = 18;
graduate.setScore(100);
graduate.testing();
graduate.info();
}
}
7.Object是所有类的父类,父类的构造器调用不限于直接父类,将一直往上追溯到Object类
8.子类只能直接继承一个父类,子类和父类之间必须满足逻辑关系.
3.继承的本质
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();
}
}
class GrandPa{//爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father{
String name = "大头爸爸";
int age = 39;
}
class Son{
String name = "大头儿子";
}
【内存分析】
4.super关键字
3.this和super的区别就在于this从本类开始访问,super从父类开始访问
5.fifinal 关键字
6.方法重写
1.方法重写就是子类中有一个方法,和父类中的某个方法的名称,参数完全一样,
返回类型相同或者是父类返回类型的子类,子类方法不能缩小父类方法的访问权限

【举例】
public class OverrideExercise01 {
public static void main(String[] args) {
Person person = new Person("wang",18);
System.out.println(person.say());
Student1 student = new Student1("wang",18,10001,100);
System.out.println(student.say());
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String say(){
return "hello大家好我叫"+name+"我今年"+age+"岁了";
}
}
class Student1 extends Person{
private int id;
private double score;
public Student1(String name, int age, int id, double score) {
super(name, age);
this.id = id;
this.score = score;
}
public String say(){
return super.say()+"我的学号是"+id+"我的成绩是"+score;
}
}
5.多态
1.向上转型
【举例】
public class Animal {
String name;
int age = 19;
public void sleep(){
System.out.println("睡");
}
public void run(){
System.out.println("跑");
}
public void eat(){
System.out.println("吃");
}
public void show(){
System.out.println("hello,你好啊,祝你平平安安");
}
}
public class Cat extends Animal{
int age = 18;
public void eat(){
System.out.println("小猫吃鱼");
}
public void catchMouse(){
System.out.println("小猫抓老鼠");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Cat();
animal.name = "小猫";
animal.eat();
animal.show();
animal.sleep();
animal.run();
}
}
2.向下转型
1.向上转型后无法调用子类特有的方法,此时可以再通过向下转型来调用,
2.语法:子类类型 引用名 = (子类类型)父类引用(父类引用必须指向当前目标类型的对象)
3.向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入 了 instanceof ,如果该表达式为true,则可以安全转换。
instanceof()用来判断对象的运行类型是否为XX类型或其子类型
4.属性没有重写之说,属性的值看编译类型,方法的调用看运行类型
【以上述代码为例】
public class Test {
public static void main(String[] args) {
//向上转型
Cat cat1 = new Cat();
Animal animal = cat1;
//结果为true,animal和cat指向同一个对象,所以地址相同
System.out.println(animal == cat1);
animal.name = "小猫";
animal.eat();
animal.show();
animal.sleep();
animal.run();
//属性的值看编译类型
System.out.println(animal.age);//19
//向下转型
//判断是否能转
if(animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
3.动态绑定机制
1.当调用对象方法时,该方法会和该对象的运行类型/内存地址绑定
2.当调用对象属性时,没有动态绑定机制,哪里声明就在哪里使用
3.总的来说就是(每一次的)调用方法都从运行类型开始找,而属性的值则是在哪个类里使用,就用哪个类的值
4.equals方法
== 和 equals的对比
1.==是一个比较运算符,在判断基本运算类型时,判断的是值是否相等,
判断引用类型时,判断的是地址是否相等,即判定是不是同一个对象.
2.equals方法只能判断引用类型,默认是判断地址,但子类往往会重写该方法
5.abstract修饰抽象类
1.抽象类比普通类多一些抽象方法(0-n),抽象方法没有方法体,只有方法声明
只有方法声明的还有一类方法称为本地方法,使用native关键字声明
2.抽象类必须有子类,只能通过子类向上转型实例化
3.抽象类不一定有抽象方法,抽象方法一定在抽象类中
4.普通子类继承抽象方法,必须重写抽象类中所有抽象方法
5.抽象子类继承抽象方法,选择重写抽象方法即可
6.abstrsct不可和private或final关键字一起使用
【】如果要求子类必须重写父类的某个方法,则推荐使用继承类
public abstract class Abstract01 {
public String name;
public int age;
public Abstract01(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void test01();
}
class Abstract02 extends Abstract01{
public Abstract02(String name, int age) {
super(name, age);
}
public void test01(){
System.out.println("这是父类抽象方法的重写");
}
public void test02(){
System.out.println("这是子类特有的方法");
}
}
class Test02{
public static void main(String[] args) {
Abstract01 abstract01 = new Abstract02("锦鲤",20);
abstract01.test01();
if(abstract01 instanceof Abstract01){
Abstract02 abstract02 = (Abstract02) abstract01;
abstract02.test02();
}
}
}
6.接口
1.接口中只存在全局常量和抽象方法,接口中不存在构造方法与普通方法
使用interface关键字,接口命名规范,使用大写的i开头
2.接口的普通子类必须重写接口中所有抽象方法,
若普通子类同时实现多个接口,则必须重写接口中的全部方法
接口不能继承类,但是可以同时继承多个父接口
普通子类先继承一个类,在实现一个或多个接口
3.使用implement关键字实现接口
4.接口子类命名以接口名称开头以Impl结尾
5.在接口中public static final abstract 全部省略
6.接口的实例化:子类向上转型
7.接口不能继承类,但是可以多继承父接口
public interface IMessage {
//在接口中public static final abstract 全部省略
//全局变量
public static final String MSG = "test";
//抽象方法
public abstract void print();
}
interface IM02{
void print02();
}
class MessageImpl extends Interfac01 implements IMessage,IM02{
public void print03(){
System.out.println("抽象类中抽象方法的重写");
}
public void print(){
System.out.println(MSG);
}
public void print02(){
System.out.println("接口方法的重写");
}
}
class Test{
public static void main(String[] args) {
IMessage iMessage = new MessageImpl();
iMessage.print();
IM02 im02 = new MessageImpl();
im02.print02();
Interfac01 interfac01 = new MessageImpl();
interfac01.print03();
}
}
7.接口优先原则
开发中优先考虑使用接口