Java基础7
面向对象的特征一:封装性
随着我们系统越来越复杂,类会越来越多,那么类之间的访问边界必须把握好,面向对象的开发原则要遵循“高内聚、低耦合”
高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。
何为封装性?
所谓封装性,就是把客观事物封装成抽象概念的类,并且类可以把自己的数据和方法只向可信的类或者对象开放,向没必要开放的类或对象隐藏信息。
权限修饰符
4种权限修饰符: private / 缺省 / protected / public
可以使用4种权限修饰符修饰类及类的内部成员。当这些成员被调用时,体现可见性的大小。
实际案例: 在题目中,我们给Animal的对象的legs属性赋值。在实际的常识中,我们知道legs不能赋值为负数的。到那会是如果直接调用属性legs没事不可以加入逻辑判断的,为了解决这个问题:
> 将legs属性私有化(private),禁止在Animal类的外部直接调用此属性
> 提供给legs属性赋值的setLegs()方法,在此方法中加入legs赋值的判断逻辑 if(l >= 0 && l % 2 == 0) 将此方法暴露出去,使得Animal类的外部调用此方法,对legs属性赋值。
> 提供给legs属性获取的getLegs()方法,此方法对外暴露。使得在Animal类的外部还可以调用此属性的值。
public class AnimalTest { public static void main(String[] args){ Animal animal1 = new Animal(); animal1.name = "小兔"; // animal1.legs = -4; 这里的赋值其实是不合理的,所以为了将这种不合理的赋值消灭 我们可以写一个赋值的方法,并取消这种.的赋值方法 animal1.setLegs(4); // 那么相应的我们输出就不能写: // System.out.println(animal1.legs); 因为我们不能够.的方式调用 所以我们还需要一个获取legs值的方法 System.out.println(animal1.getLegs()); animal1.eat(); } } class Animal{ String name; private int legs; // 为了防止用户用.的方式去赋值legs public void eat(){ System.out.println("动物觅食"); } public void setLegs(int l){ if(l >= 0 && l % 2 == 0){ legs = l; }else{ System.out.println("你输入的数据非法!"); } } public int getLegs(){ return legs; } }
权限修饰符的范围
类: 只能使用public / 缺省 修饰
类的内部成员: 可以使用4种权限修饰
封装性的体现
> 场景1: 私有化(private)类的属性,提供公共(public)的get和set方法,对此属性进行获取或修改
> 场景2: 将类中不需要对外暴露的方法,设置为 private
> 场景3: 单例模式中构造器private(私有)的了,避免在类的外部创建实例。
构造器
作用1:搭配new关键字,创建类的对象。
作用2:在创建对象的同时,可以给对象的相关属性赋值
格式: 权限修饰符 类名(形参列表){ }
注意: 创建类以后,在没有显示提供任何构造器的情况下,系统会默认提供一个空参的构造器,且构造器的权限与类声明的权限相同。
一旦类中显示声明了构造器,则系统不再提供默认的空参的构造器。
public class Student { String name; int age; String school; String major; /* *与类名一致的方法名 * 构造方法是在创建对象的时候调用 * 类在没有定义构造方法的时候有一个默认的无参构造 * 初始化成员变量 */ public Student (String n, int a){ name = n; age = a; } public Student (String n, int a, String s){ name = n; age = a; school = s; } public Student (String n, int a, String s, String m){ name = n; age = a; school = s; major = m; } public String getInfo(){ return "name = " + name + ",age = " + age + ",school = " + school + ",major = " + major; } } public class StudentDemo { public static void main(String[] args){ Student s=new Student("小明", 19); System.out.println(s.age); System.out.println(s.getInfo()); } }
属性赋值过程
在类的属性中,有哪些位置给属性赋值:
① 默认初始化;
② 显式初始化;
③ 构造器中初始化;
④ 通过“对象.方法”的方式赋值;
⑤ 通过“对象.属性”的方式赋值;
执行的先后顺序: ① - ② - ③ - ④ / ⑤
以上操作在对象创建过程中可以执行的次数如何:
> 只能执行一次: ①、②、③
> 可以多次执行: ④、⑤
JavaBean
JavaBean是一种Java语言写成的可重用组件。
好比做了一个扳手,这个扳手会在很多地方被拿去用。这个扳手也提供多种功能(可以拿这个扳手扳、锤、撬等),而这个扳手就是一个组件。
所谓JavaBean,是符合如下标准的java类:
① 类是公共的 ② 有一个无参的公共的构造器 ③ 有属性,且有对应的get、set方法
UML类图
常用的UML工具软件有 PowerDesinger、Rose和 Enterprise Architect。
UML工具软件不仅可以绘制软件开发中所需的各种图表,还可以生成对应的源代码。
在软件开发中,使用UML类图可以更加直观地描述类内部结构(类的属性和操作)以及类之间的关系(如关联、依赖、聚合等)
- + 表示public类型, - 表示private类型, # 表示protected类型
- 方法的写法: 方法的类型(+、-) 方法名(参数名:参数类型):返回值类型
- 斜体表示抽象方法或类
this关键字
目前出现的问题:
声明的一个属性对应的setXXX方法时,通过形参给对应的属性赋值。如果形参名和和属性名同名了,那么该如何在方法内区分这两个变量
解决方案: 使用this。具体来讲,使用this修饰的变量,表示的是属性。没有使用this修饰的,表示的是形参。
this功能
可以调用:成员变量、方法、构造器
this一般理解为 当前对象(在方法中调用时) 或 正在创建的对象 (在构造器中调用时)
public class Boy {
private String name;
private int age;
public Boy(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public void marry(Girl girl){
System.out.println("我想娶" + girl.getName());
}
public void shout(){
}
}
public class Girl {
private String name;
private int age;
public Girl(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void marry(Boy boy) {
System.out.println("我想嫁给" + boy.getName());
boy.marry(this); //调用boy的marry,并使用this关键字把当前的女孩对象传入 得到的就是当前女孩的名字
}
public int compare(Girl girl){ //比较两个对象的年龄大小
if (this.age > girl.age){
return 1;
}else if (this.age < girl.age){
return -1;
}else{
return 0;
}
}
}
public class Test {
public static void main(String[] args){
Boy boy1 = new Boy("杰克",23);
Girl girl1 = new Girl("朱丽叶",21);
girl1.marry(boy1);
Girl girl2 = new Girl("rose",19);
int compare = girl1.compare(girl2);
if(compare > 0){
System.out.println(girl1.getName() + "大");
}else if(compare < 0){
System.out.println(girl2.getName() + "大");
}else {
System.out.println("一样大");
}
}
}
this调用属性和方法
- 针对于方法内的使用情况:(准确的说是非static修饰的方法)
一般情况:通过对象a调用方法,可以在方法内调用当前对象a的属性或其他方法。此时,我们可以在属性和其他方法前使用“this”,表示当前属性或方法所属的对象。但是一般情况下,我们都选择省略此“this”结构
特殊情况:如果方法的形参与对象的属性同名了,我们必须使用“this.”进行区分。使用this.修饰的变量即为属性(或成员变量),没有使用this.修饰的即为局部变量。
- 针对于构造器内的使用情况:
一般情况:通过构造器创建对象时,可以在构造器内调用当前正在创建的对象的属性或方法。此时,我们可以在属性和方法前使用“this”,表示当前属性或方法所属的对象。但是一般情况下,我们都选择省略此“this”结构
特殊情况:如果构造器的形参与正在创建的对象的属性同名了,我们必须使用“this.”进行区分。使用this.修饰的变量即为属性(或成员变量),没有使用this.修饰的即为局部变量。
public class PersonTest {
public static void main(String[] args){
Person p1 = new Person("Tom","tom@126.com");
p1.setAge(10);
}
}
class Person{
String name;
int age;
String email;
public Person(String name, String email){ //构造器
this.name = name;
this.email = email;
}
public void setAge(int age){ //这里为了见名知意 最好还是把变量名设置为age
this.age = age;
}
public int getAge(){
return this.age;
}
}
this调用构造器
我们可以在类的构造器中调用当前类中指定的其它构造器。
格式: this(形式参数)
要求:this(形参列表)必须声明在当前构造器的首行
结论:this(形参列表)在构造器中最多声明一个 如果一个类中声明了n个构造器,则最多有n-1个构造器可以声明有this(形参列表)的结构 不要形成环相互调用
public class PersonTest {
public static void main(String[] args){
//虽然构造器里面用this调用了构造器,但是只new了一个对象 所以只创建了1个Person类对象
Person p1 = new Person(16);
}
}
class Person{
String name;
int age;
String email;
public Person(){
//
}
public Person(int age){
this(); //这里调用的就是上面的空参的构造器
this.age = age;
}
public Person(String name, String email){ //构造器
this.name = name;
this.email = email;
}
}
例子:
public class Account {
private double balance;
public Account(double balance){
this.balance = balance;
}
public double getBalance(){
return balance;
}
public void deposit(double amt){
if(amt > 0 && balance >- amt){
balance -= amt;
System.out.println("成功取出" + amt);
}else {
System.out.println("取款数额有误或者余额不足!");
}
}
public void withdraw(double amt){
if (amt > 0){
balance += amt;
System.out.println("成功存入" + amt);
}
}
}
public class Customer {
String firstName;
String lastName;
Account account;
public Customer(String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Account getAccount() {
return account;
}
public void setAccount (Account acct){
account = acct;
}
}
public class Bank {
private Customer[] customers; //保存多个客户
private int numberOfCustomer; //存储的 客户个数
public Bank(){
customers = new Customer[10];
}
public void addCustomer(String f, String l){
Customer c = new Customer(f,l);
customers[numberOfCustomer] = c;
numberOfCustomer++;
}
public int getNumberOfCustomer(){
return numberOfCustomer;
}
public Customer getCustomer(int index){
if(index < 0 || index >= numberOfCustomer){
return null;
}else{
return customers[index];
}
}
}
public class Test {
public static void main(String[] args){
Bank bank = new Bank();
bank.addCustomer("明", "小");
bank.addCustomer("红", "小");
bank.getCustomer(0).setAccount(new Account(3000));
bank.getCustomer(0).getAccount().withdraw(60);
System.out.println("账户余额:" + bank.getCustomer(0).getAccount().getBalance());
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具