该文章Github地址:https://github.com/AntonyCheng/java-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】
在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!
上一章:由浅到深认识Java语言(17):内部类
28.权限修饰符
权限修饰符 { p u b l i c d e f a u l t p r o t e c t e d p r i v a t e \bf{权限修饰符}\begin{cases}\bf{public}\\\bf{default}\\\bf{protected}\\\bf{private}\end{cases} 权限修饰符⎩ ⎨ ⎧publicdefaultprotectedprivate
public 公共权限
在任何地方都能够使用,可以修饰类,也可以修饰属性,还可以修饰方法和构造器;
这里的任何地方指的是不同包之间都可以调用的元素;
示例如下:
packageOne:
A 类:
package top.sharehome.Bag1;
public class A {
public String str = "A.str" ;
}
B 类:
package top.sharehome.Bag1;
public class B {
public void method() {
System.out.println("B.method()");
}
}
packageTwo:
Demo 类:
package top.sharehome.Bag2;
import top.sharehome.Bag1.A;
import top.sharehome.Bag1.B;
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = new B();
System.out.println(a.str);
b.method();
}
}
打印效果如下:
default 默认权限(不加修饰符)
也称 package 权限 (包级权限) ,可以修饰类,也可以修饰属性,还可以修饰方法,但不能修饰构造器;
权限要求是只在本包内进行调用的元素,不可在不同包之间互相调用;
示例如下:
packageOne:
A 类:
package top.sharehome.Bag1;
class A {
String str = "A.str";
}
B 类:
package top.sharehome.Bag1;
class B {
void method() {
System.out.println("B.method()");
}
}
packageTwo:
Demo 类:
package top.sharehome.Bag2;
import top.sharehome.Bag1.A; //因为调用不到,所以这里会报错
import top.sharehome.Bag1.B; //也是因为调用不到,所以这里也会报错
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = new B();
System.out.println(a.str);
b.method();
}
}
protected 受保护权限
该权限大都应用在非本包的项目内;
在本包下,相当于 default;
在非本包下:对于非子孙类相当于 private;对于子孙类相当于 public;
protected 可以修饰属性,方法和构造器;
private 私有权限
private 只能修饰属性,方法和构造器;
private 只能在本类中进行访问和调用;
29.Java中的包
定义:包就是对类实现统一管理的容器,一个类的完整类名应该是 包名+类名;
注意:类的首行需要说明该类所在的包;
//package 包名;
package top.sharehome.Bag;
类的导入:
//import 包名.类名; //包内单个类
//import 包名.*; //包内所有的类
//例如下:
import top.sharehome.Bag.A;
import top.sharehome.Bag.*;
如果只想创建一次某一个包内某一类的对象:
//包名.类名 对象名 = new 包名.类名();
//例如下:
top.sharehome.Bag.A a = new top.sharehome.Bag.A();
30.Object类
所有类的父类,都是 Object,意味着 Object 类中所有的结构,每个类都会拥有;
Object类中的结构
JDK:java 的开发工具集中包含了一个 lib 文件(类库),该文件中存放着 java 出版商已经设计好的各种类,这些类供我们使用;
lib 文件位置:\Java\lib
Object 类中的方法:
返回类型 | 方法解释 |
---|---|
protected Object | clone() 创建并返回此对象的一个副本。 |
boolean | equals(Object obj) 指示其他某个对象是否与此对象“相等”。 |
protected void | finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 |
Class<?> | getClass() 返回此 Object 的运行时类。 |
int | hashCode() 返回该对象的哈希码值。 |
void | notify() 唤醒在此对象监视器上等待的单个线程。 |
void | notifyAll() 唤醒在此对象监视器上等待的所有线程。 |
String | toString() 返回该对象的字符串表示。 |
void | wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 |
void | wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 |
void | wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 |
toString()方法
**作用:**返回该对象的字符串表示,返回值是 String;
实例如下:
package top.sharehome.Package;
public class Demo {
public static void main(String[] args) {
Student Stu = new Student();
Stu.setName("小陈");
Stu.setAge(18);
System.out.println(Stu.toString()); //这里运用的是toString方法
}
}
class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
当直接打印一个对象时,看到的是一个哈希码值(hashCode);
即上图中的 372f7a8d
,也就是说 System.out.println(对象) 会直接调用对象所继承的 toString() 方法;
Object 类中的 toString() 方法如下:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
所以就能解释打印结果了;
Q : Q: Q: 但是我们希望我们打印的方法是对象里每一个具体的值?
A : A: A: 因为是从 Object 类中继承过来的,所以我们可以通过方法的重写来实现;
package top.sharehome.Package;
public class Demo {
public static void main(String[] args) {
Student Stu = new Student();
Stu.setName("小陈");
Stu.setAge(18);
System.out.println(Stu.toString());
}
}
class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//toString方法的重写
public String toString() {
String message = "姓名:"+this.name + " "+"年龄:"+this.age;
return message;
}
}
打印效果如下:
注意: eclipse 有直接重写 toString 的快捷方式 ==> Ctrl+Shift+S
==> Generate toString()
equals(Object obj)方法
**作用:**每个对象都会有一个 equals() 方法,用于比较当前对象是否和参数传进来的对象相等,返回值是 boolean;
Object 类中的 equals(Object obj) 方法如下:
public boolean equals(Object obj) {
return (this == obj);
}
比较运算符 ”==“ 的两种结果:
-
对于基本数据类型来说,”==“ 比较的是基本数据类型的值是否相等;
-
对于引用数据类型来说,”==“ 比较的是引用数据类型的地址值是否相等;
对于任何两个对象来说,地址值必然不同,例如下:
package top.sharehome.Bag; public class Demo { public static void main(String[] args) { Student s1 = new Student("小陈", 20); Student s2 = new Student("小陈", 20); Boolean result1 = s1.equals(s2); //不同对象 Boolean result2 = s1.equals(s1); //相同对象 System.out.println(result1); System.out.println(result2); } } class Student { private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
打印效果如下:
Q : Q: Q: 但是我们希望比较两个对象完全相同的依据是对象的属性是否完全相同?
A : A: A: 所以我们得对 equals(Object obj) 方法重写;
equals(Object obj) 方法重写:
原理:
当前对象是 this ,比较对象是 obj;
比较两个对象的 name 和 age 属性是否完全相同,相同则 false ,否则 true;
就如上例:
package top.sharehome.Bag;
public class Demo {
public static void main(String[] args) {
Student s1 = new Student("小陈", 20);
Student s2 = new Student("小花", 20);
Boolean result1 = s1.equals(s2);
Boolean result2 = s1.equals(s1);
System.out.println(result1);
System.out.println(result2);
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) { //这里运用多态:Object obj = new Student(String name,int age);
//这里发现父类中没有 name 和 age,但是子类 Student类中有,所以要向下转型:instanceof + 强行转换
if (obj instanceof Student) {
Student Stu = (Student) obj;
//判断age是否相同
if(this.age == Stu.age) {
//判断name是否相同:因为String类型是引用数据类型,所以不能用"=="简单比较;
//但是用"=="比较也会有相同结果,但是对于引用数据的对比需规范 equals
if(this.name.equals(Stu.name)) {
return true;
}else {
return false;
}
}else {
return false;
}
}
return false;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
打印效果如下:
**注意:**eclipse 有直接重写 equals 的快捷方式 ==> Ctrl+Shift+S
==> Generate hashCode() and equals()
;
如下例就是完全依靠 eclipse 写出的 Student 类:
package top.sharehome.Bag;
import java.util.Objects;
public class Demo {
public static void main(String[] args) {
Student Stu1 = new Student("小陈",20,"女");
Student Stu2 = new Student("小陈",20,"女");
Student Stu3 = new Student("小伍",20,"男");
System.out.println(Stu1.equals(Stu2));
System.out.println(Stu1.equals(Stu3));
}
}
class Student {
private String name;
private int age;
private String sex;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public int hashCode() {
return Objects.hash(age, name, sex);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
return age == other.age && Objects.equals(name, other.name) && Objects.equals(sex, other.sex);
}
}
打印效果如下:
hashCode()方法(详情在集合)
该方法能够产生一个对象的哈希码值,哈希码值决定了该对象在内存的存放位置;
Object 类中的 hashCode() 方法如下:
@IntrinsicCandidate
public native int hashCode();