(一)学习总结
1.什么是构造方法?什么是构造方法的重载?下面的程序是否可以通过编译?为什么?
- 构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法用于在创建对象时对其进行初始化。
- Person per = new Person() ;
- 特点:
- ①方法名与类名相同;
- ②方法名前没有返回值类型的声明,方法中不能使用return语句返回一个值;
- ③用户不能直接调用,而是通过关键字new自动调用
- ④在构造方法的实现中,也可以进行方法重载。
- 如果一个类中没有声明一个明确的构造方法,则Java运行时系统会自动提供缺省的构造方法,它没有任何参数,什么也不做。
- 构造方法的重载就是方法名称相同,但参数的类型和参数的个数不同,通过传递参数的个数及类型不同以完成不同功能的方法调用。
public class Test {
public static void main(String args[]) {
Foo obj = new Foo();
}
}
class Foo{
int value;
public Foo(int intValue){
value = intValue;
}
}
- 不能通过编译
- 类中只定义了有参的构造函数,如果一个类中已经明确定义了构造方法,则系统不再提供默认的构造方法。
- 为了避免出现错误,在一个类中如果定义了一个有参的构造方法时,最好再定义一个无参的构造方法。
2.运行下列程序,结果是什么?分析原因,应如何修改。
public class Test {
public static void main(String[] args) {
MyClass[] arr=new MyClass[3];
arr[1].value=100;
}
}
class MyClass{
public int value=1;
}
- 运行结果:Exception in thread "main" java.lang.NullPointerException
- 原因:只声明了对象,而没有完成对象实例化。类是引用数据类型,所以数组里的每一个对象都是null值,在使用时必须分别进行实例化操作。
- 应该对数组里的每个对象元素,通过new构造方法进行动态或静态实例化。
3.运行下列程序,结果是什么?说明原因。
public class Test {
public static void main(String[] args) {
Foo obj1 = new Foo();
Foo obj2 = new Foo();
System.out.println(obj1 == obj2);
}
}
class Foo{
int value = 100;
}
- 运行结果:false
- 类是引用数据类型,两个对象都是通过new开辟的不同的新的空间,所以obj1和obj2分别代表两个对象的地址,两个新开辟的地址空间不同,所以返回false。
4.什么是面向对象的封装性,Java中是如何实现封装性的?试举例说明。
- 封装性就是把对象的成员属性和成员方法结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节。
- 要对数据进行封装,通常用关键字private声明属性
- private String number;
- private int balance;
- private int bonus;
- 在JAVA开发的标准规定中,封装属性的设置和取得依靠setter及getter方法完成
- setter:设置属性的值
public void setBalance(int balance) {
this.balance = balance;
}
- getter:调用该属性的值
public int getBalance() {
return balance;
}
- 封装把对象的所有组成部分(数据和方法)封装在一起构成类。
- 对象本身的数据得到保护/隐藏
- 其他对象通过该对象的访问方法(接口/interface)与之发生联系。
- 好处
- 模块化
- 信息隐藏--通常定义一个公共接口/方法实现对对象的访问。
5.阅读下面程序,分析是否能编译通过?如果不能,说明原因。
- (1)
class A{
private int secret = 5;
}
public class Test{
public static void main(String args[]){
A a = new A();
System.out.println(a.secret++);
}
}
- 不能通过编译。secret属于A类的私有属性,不能在类外直接访问。
- (2)
public class Test{
int x = 50;
static int y = 200;
public static void method(){
System.out.println(x+y);
}
public static void main(String args[]){
Test.method();
}
}
- 不能通过编译。method只能访问被static修饰的变量,而x没有被static修饰。
6.使用类的静态变量和构造方法,可以跟踪某个类创建的对象个数。声明一个图书类,数据成员为编号,书名,书价,并拥有静态数据成员册数记录图书的总数。图书编号从1000开始,每产生一个对象,则编号自动递增(利用静态变量和构造方法实现)。下面给出测试类代码和Book类的部分代码,将代码补充完整。
class Book{
int bookId;
String bookName;
double price;
// 声明静态变量
public static n;
//定义静态代码块对静态变量初始化
static {
n=0;
}
//构造方法
public Book(String bookName,double price ){
this.bookName=bookName;
this.price =price ;
n++;
this.bookId=1000+n;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//定义方法求图书总册数
public int totalBook(){
return n;
}
//重写toString方法
public string toString(){
return "编号"+bookld+"书名"+bookName+"价格"+"price "+"图书总数目为"+n;
}
}
public class Test{
public static void main(String args[]){
Book[] books = {new Book("c语言程序设计",29.3),
new Book("数据库原理",30),
new Book("Java学习笔记",68)};
System.out.println("图书总数为:"+ Book.totalBook());
for(Book book:books){
System.out.println(book.toString());
}
}
}
7.什么是单例设计模式?它具有什么特点?用单例设计模式设计一个太阳类Sun。
- 单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
- 单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
- 类可以灵活更改实例化过程。
class Sun{
private Sun instance = new Sun();
private Sun(){
}
public static Sun getInstance(){
return instance;
}
}
8.理解Java参数传递机制,阅读下面的程序,运行结果是什么?说明理由。
public class Test {
String str = new String("你好 ");
char[] ch = { 'w','o','l','l','d' };
public static void main(String args[]) {
Test test = new Test();
test.change(test.str, test.ch);
System.out.print(test.str);
System.out.print(test.ch);
}
public void change(String str, char ch[]) {
str = "hello";
ch[0] = 'W';
}
}
- 运行结果:你好 Wolld
- 原因:str属于引用类型,调用change方法把地址传入,在change方法中改变了str的值后释放地址空间,没有改变主方法中str的值。而ch代表数组的地址,调用change方法改变了ch第一个字符的值后将ch传回主方法。
9.this关键字
- this的使用场合
- 方法中有与成员变量同名的局部变量,或方法的入口参数与成员变量同名时,用this关键字指明成员变量以实现对它的访问;另外在程序易于产生二义性的地方,也 可使用this指明当前对象以使代码更清晰。
- 注意事项:this不能在类定义的外部使用,只能在类定义的方法中使用
- 使用this关键字明确访问一个类的成员变量,解决与局部变量名称冲突问题。
- 使用this调用构造方法
- 构造方法是在实例化对象时被java虚拟机自动调用的,在程序中不能像调用其他方法一样去调用构造方法,但可以在一个构造方法中使用this([参数1,参数2,...])的形式来调用其他的构造方法。
class Person{
private String name ;
private int age ;
public Person(){
System.out.println("无参构造方法被调用");
}
public Person(String name){
this();
System.out.println("一个参数的构造方法被调用");
this.name = name ;
}
public Person(String name,int age){
this(name);
System.out.println("两个参数的构造方法被调用");
this.age = age ;
}
public String toString(){
return "姓名:" + name + ",年龄:" + age ;
}
}
public class Test{
public static void main(String args[]){
Person per1 = new Person("张三",33) ;
System.out.println(per1.toString()) ;
}
}
- 运行结果:
- 无参构造方法被调用
- 一个参数的构造方法被调用
- 两个参数的构造方法被调用
- 姓名:张三,年龄:33
- 注意事项:
- 只能在构造方法中使用this调用其他的构造方法,不能再成员方法中使用。
- 在构造方法中,使用this调用构造方法的语句必须放在第一行,且只能出现一次。
- 不能在一个类的多个构造方法中使用this互相调用,必须保留一个不用this调用其他构造方法的情况,作为出口。
class Person{
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
}
public boolean compare(Person per){
Person p1 = this ;// 当前的对象
Person p2 = per ;// 传递进来的对象
if(p1==p2){ return true ; }
if(p1.name.equals(p2.name)&&p1.age==p2.age){
return true ;
}else{
return false ;
}
}
public class Test{
public static void main(String args[]){
Person per1 = new Person("张三",30) ;
Person per2 = new Person("张三",30) ;
if(per1.compare(per2)){
System.out.println("两个对象相等!") ;
}else{
System.out.println("两个对象不相等!") ;
}
}
10.static关键字
- static关键字在类中可以声明变量或方法。
- 静态变量(类变量)
- 用static声明的变量称为静态变量(类变量、全局变量),不带static的变量都是实例变量。
- 实例变量存储在对象的内存单元中,每个对象的实例变量都有自己的存储空间,通过对象名访问这些实例变量。
- 静态变量被保存在类的内存区的公共存储单元中,而不是保存在某个对象的内存区中。因此,一个类的任何对象访问它时,存取到的都是相同的数值。一个类的任何对象修改它,都是对同一内存单元进行操作。可以通过类名或对象名访问它,一般是通过类名完成调用。
- 静态变量初始化时,变量被计算和赋值,此过程只有一次。
class Person {
private String name ;
private int age ;
private String university ;
public Person(String name,int age,String university){
this.name = name ;
this.age = age ;
this.university=university;
}
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age + ",学校:" +this.university ;
}
}
public class Test{
public static void main(String args[]){
Person per1 = new Person("张三",20,"成都电子科技大学") ;
Person per2 = new Person("李四",21,"复旦大学") ;
System.out.println(per1.toString()) ;
System.out.println(per2.toString()) ;
}
}
- 运行结果:
- 姓名:张三,年龄:20,学校:成都电子科技大学
- 姓名:李四,年龄:21,学校:复旦大学
(二)实验总结
本次实验包括实验二和实验三两次的内容:
1.用面向对象思想完成评分系统
- 设计思路:
- 1.创建一个选手类,基本属性:编号,姓名,最终得分,定义构造方法、getter和setter方法、toSting方法,实现Comparable接口,完成对象比较方法。
- 2.创建一个评分类,基本属性:评委人数,评委给出的分数。定义构造方法、 getter和setter方法、分数输入方法inputScore(),计算平均分avarage(double score[])
- 3. 创建一个测试类,在测试类中创建选手对象,为每位选手打分(评分类),所有选手评分完毕后,给出排行榜,包括如下信息(选手编号,选手姓名,选手得分)
2.Email验证
- 设计思路:
- 创建一个布尔类型方法判断email有效的四个条件,四个条件都满足时返回true,有一个条件不满足则返回false。
- 在主方法中验证,输入一个email地址,调用判断方法,返回值为true,输出地址有效,否则无效。
3.查找子串
- 设计思路:
- 首先用,将输入的字符串分离;
- 判断要查找的字符串是存在于原字符串中。存在则继续查找,不存在结束统计。
- 第一次找到要查找的字符串后得到第一次出现该字符串的下标并且将已知字符串从第一次出现要查找的字符串的位置后取出,得到新的字符串。
- 将新得到的字符串作为统计方法的新的参数,递归调用统计方法。
- 输出字符串要查找的字符串在已知字符串中出现的的次数。
4.统计文件
- 设计思路:
- 首先将字符串用,拆分。
- 将拆分得到的字符串数组的每个元素用 . 拆分,用一个新的数组存储每个文件的文件类型。
- 统计每个文件类型出现的次数。
- 问题:
- 1.String的比较有两种方式:
==:用于数值的比较,比较的是两个字符串的地址值
equals()方法:用于内容的比较,比较两个字符串内容是否相等
- 2. 输出转义字符要加 ,sqrt("\.")
5.类的设计
- 设计思路:
- (1)设计一个日期类,用于记录年、月、日,提供对日期处理的常用方法(日期输出格式xxxx-xx-xx)。
- (2)设计一个职工类,该职工类至少具有下面的属性:职工号,姓名,性别,生日,工作部门,参加工作时间,设计相应的方法。
- (3)设计一个部门类,包括下列属性:部门编号,部门名称,经理,设计相应方法。
- (4)设计一个测试类,采用对象数组模拟一个拥有两个部门,10个职工的单位,实现对相关信息的查询功能。
- 问题:
- 职工类的生日属于日期类,在输出是使用日期类的tostring方法。