文章原载于我的个人博客,欢迎来访。
整理了一些Java编程基础的知识点以及代码。
其实是选修课作业附件:部分源代码
(1)首先从Oracle官方网站下载安装适合系统的JDK,按默认安装路径进行JDK安装即可。
(2)配置环境变量:在系统环境变量中新建变量JAVA_HOME
,值为JDK的安装路径;将%JAVA_HOME%\bin
添加到系统变量Path。
设置环境变量如图所示
JAVA_HOME= C:\Program Files\Java\jdk1.8.0_92
CLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
PATH=%PATH%;%JAVA_HOME%\bin
注意:
%PATH%
为原来的环境变量值,添加";"和后面的内容到原来值的后面。
验证是否配置成功,可点击开始→运行,输入cmd打开命令行窗口,输入java -version
,显示版本,如图。说明JDK安装及环境变量配置成功。
(3)编写并运行:用记事本编码并存储在D盘;Win+R到命令行D:
,找到java文件;命令行输入javac HelloWorld.java
编译生成class文件,命令行输入java HelloWorld
运行
答案:B
A. java.exe B. javac.exe C. javap.exe D. javaw.exe
答案:java,class
答案:D
A. public void main(String args[ ])
B. static void main(String args[ ])
C. public static void Main(String args[ ])
D. public static void main(String args[ ])
public class Homework1 {
public static void main(String[] args) {
for (char ch = 'A'; ch <= 'Z'; ch++) {
System.out.print(ch + " ");
}
}
}
运行结果:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
public class Homework2 {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("1 + 2 + 3 + … + 100 = " + sum);
}
}
运行结果:
1 + 2 + 3 + … + 100 = 5050
类是对一类对象的描述;对象是类的具体实例。Java中创建对象前需要创建对象引用:类名 引用变量名
;使用new关键字创建一个新的对象:new 类名( [初始化参数] )
。
例:
Clock clock;
clock = new Clock(12, 30, 15);
**实例变量(属于对象的属性):**没有 static 修饰的变量(数据成员)称为实例变量;存储所有实例都需要的属性,不同实例的属性值可能不同;可通过表达式 实例名.实例变量名
访问实例属性的值。
**类变量(静态变量)(为该类的所有对象共享):**用 static 修饰;在整个类中只有一个值;类初始化的同时就被赋值。适用情况于类中所有对象都相同的属性、经常需要共享的数据和系统中用到的一些常量值。引用格式:类名或实例名.类变量名
**实例方法:**用来表示每一个实例对象的功能或者行为。表示特定对象的行为;声明时前面不加 static 修饰符;实例方法调用格式:对象名.方法名([参数列表])
;
例:
public class Circle {
double radius;
static final double PI = 3.14159;
Circle(double r){
radius = r;
}
public double area() {
return PI * radius * radius;
}
}
radius 是实例变量,PI 是类变量,area() 是实例方法。他们的调用方法如下:
public class ShapeTester {
public static void main(String[] args) {
Circle circle = new Circle(2.5);
System.out.println(Circle.PI);
System.out.println(circle.PI);
System.out.println(circle.radius);
System.out.println(circle.area());
}
}
运行结果:
3.14159
3.14159
2.5
19.6349375
类继承的语法为:
[ClassModifier] class ClassName extends SuperClassName {
//类体
}
例:
//Person.java
public class Person {
private String name;
private String gender;
private int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getGender() {
return gender;
}
public void grow() {
age++;
}
public String toString() {
return name+", "+gender+", "+age+" years old";
}
}
//Student.java
public class Student extends Person {
private int grade;
private String id;
public Student(String name, String gender, int age,
int grade, String id) {
super(name, gender, age);
this.grade = grade;
this.id = id;
}
public int getGrade() {
return grade;
}
public String getId() {
return id;
}
@Override
public void grow() {
super.grow();
grade++;
}
@Override
public String toString() {
return getName()+", "+"Grade "+grade+", "
+getGender()+", "+getAge()+" years old"+", Student id: "+id;
}
}
//Tester.java
public class Tester {
public static void main(String[] args) {
Student Peter = new Student("Peter", "male", 18, 1, "1927405001");
Person Mary = new Person("Mary", "female", 20);
System.out.println(Peter);
System.out.println(Mary);
Peter.grow();
Mary.grow();
System.out.println("Next year.");
System.out.println(Peter);
System.out.println(Mary);
}
}
运行结果:
Peter, Grade 1, male, 18 years old, Student id: 1927405001
Mary, female, 20 years old
Next year.
Peter, Grade 2, male, 19 years old, Student id: 1927405001
Mary, female, 21 years old
继承是根据已有类来设计新类,新类具有已有类的所有功能(属性和行为)。
继承机制可以提高程序的抽象程度,提高代码的可重用性。
例如 有以下继承关系:
Java代码实现如下:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Name: " + name + "\tAge: " + age);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void play() {
System.out.println("Playing......");
}
}
public class Student extends Person {
private String studentId;
public Student(String name, int age, String id) {
super(name, age);
studentId = id;
System.out.println("Student No." + studentId);
}
public String getStudentId() {
return studentId;
}
public void study() {
System.out.println("Studying......");
}
}
public class Teacher extends Person {
private String teacherId;
public Teacher(String name, int age, String id) {
super(name, age);
teacherId = id;
System.out.println("Teacher No." + teacherId);
}
public String getTeacherId() {
return teacherId;
}
public void teach() {
System.out.println("Teaching......");
}
}
public class Tester {
public static void main(String[] args) {
Person Jack = new Person("Jack", 20);
Jack.play();
System.out.println();
Student Holger = new Student("Holger", 18, "19274001");
Holger.play();
Holger.study();
System.out.println();
Teacher Mary = new Teacher("Mary", 30, "2020270001");
Mary.play();
Mary.teach();
}
}
运行结果:
Name: Jack Age: 20
Playing......
Name: Holger Age: 18
Student No.19274001
Playing......
Studying......
Name: Mary Age: 30
Teacher No.2020270001
Playing......
Teaching......
如果子类不需要使用从超类继承来的方法,可以声明自己的同名方法,称为重写Override(方法覆盖),即外壳不变,核心重写。
重写的方法的返回类型、方法名称、参数个数必须和被覆盖的方法完全一致。访问权限可以更宽松,但不能更严格。重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
super.被覆盖的方法名();
例如 Student类重写了从Person类继承的grow方法。
Java代码实现如下:
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Name: " + name + ",\tAge: " + age);
}
public void grow() {
age++;
}
}
public class Student extends Person {
public int grade;
public Student(String name, int age, int grade) {
super(name, age);
this.grade = grade;
System.out.println("Grade " + grade);
}
@Override
public void grow() {
age++;
grade++;
}
}
public class Tester {
public static void main(String[] args) {
Person Jack = new Person("Jack", 20);
Student Holger = new Student("Holger", 18, 1);
System.out.println("One year later...");
Jack.grow();
Holger.grow();
System.out.println(Jack.name+"\t"+Jack.age);
System.out.println(Holger.name+"\t"+Holger.age+"\t"+Holger.grade);
}
}
运行结果:
Name: Jack, Age: 20
Name: Holger, Age: 18
Grade 1
One year later...
Jack 21
Holger 19 2
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。
返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造方法的重载。
重载规则:
例如:
public class Dog {
public void bark() {
System.out.println("Woof!");
}
public void bark(int num) {
for (int i = 0; i < num; i++) {
System.out.println("Woof!");
}
}
}
public class Tester {
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();
System.out.println();
dog.bark(3);
}
}
运行结果:
Woof!
Woof!
Woof!
Woof!
(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
抽象类
规定了整个类家族公共的属性和方法。
抽象方法
抽象方法的优点
例如 抽象类Animal类,Cat类和Dog类继承自Animal类。关系如下:
Java代码实现如下:
public abstract class Animal {
public abstract void run();
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void run() {
System.out.println("The cat is running.");
}
@Override
public void eat() {
System.out.println("The cat is eating cat food and fish.");
}
public void jump() {
System.out.println("The cat can jump!");
}
}
public class Dog extends Animal{
@Override
public void run() {
System.out.println("The dog is running.");
}
@Override
public void eat() {
System.out.println("The dog is eating dog food and bones.");
}
public void bark() {
System.out.println("The dog is barking. Woof!");
}
}
public class Tester {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
cat.run();
cat.jump();
System.out.println();
Dog dog = new Dog();
dog.eat();
dog.run();
dog.bark();
}
}
运行结果:
The cat is eating cat food and fish.
The cat is running.
The cat can jump!
The dog is eating dog food and bones.
The dog is running.
The dog is barking. Woof!
接口可以看做是一个“纯”抽象类,它只提供一种形式,并不提供实现。
接口中可以规定方法的原型:方法名、参数列表以及返回类型,但不规定方法主体;也可以包含基本数据类型的数据成员,但它们都默认为static和final。
接口的作用
是面向对象的一个重要机制
是继承多个设计
建立了类和类之间的“协议”:
接口允许我们在看起来不相干的对象之间定义共同行为
例如 Shape是接口。Circle 类及 Rectangle 类实现接口 Shape。关系如下图表示:
Java代码实现如下:
interface Shape {
double pi = 3.14159;
double area();
}
class Circle implements Shape {
double radius;
public Circle(double r) {
radius = r;
System.out.println("New Circle: radius = " + radius);
}
public double area() {
return (pi * radius * radius);
}
}
class Rectangle implements Shape {
int length, width;
public Rectangle(int l, int w) {
length = l;
width = w;
System.out.println("New Rectangle: length = " + length
+ ", width = " + width);
}
public double area() {
return (width * length);
}
}
public class InterfaceTester {
public static void main(String[] args) {
Circle cir;
cir = new Circle(2.0);
System.out.println("Area of Circle cir is " + cir.area());
System.out.println();
Rectangle rec;
rec = new Rectangle(5, 6);
System.out.println("Area of Rectangle rec is " + rec.area());
System.out.println();
}
}
运行结果:
New Circle: radius = 2.0
Area of Circle cir is 12.56636
New Rectangle: length = 5, width = 6
Area of Rectangle rec is 30.0
简单地说,异常(Exception,又称例外)是指程序运行时所发生的不正常的事件。原因有很多,例如除零、下标越界、文件不存在、类型错误、装载一个不存在的类或者对 null 对象操作等等。
如果这些异常得不到正确的处理将会导致程序终止运行,而合理地使用异常处理结果可以使得程序更加健壮,具有更强的容错性,不会因为用户不小心的错误输入或其他运行时原因而造成程序终止;也可以使用异常处理结构为用户提供更加友好的提示。
当Java程序出现以上的异常时,就会在所处的方法中产生一个异常对象。这个异常对象包括异常的类型,异常出现时程序的运行状态以及对该异常的详细描述。
所有的异常类是从java.lang.Exception
类继承的子类。
Exception类是Throwable类的子类。除了Exception类外,Throwable还有一个子类Error。Error用来指示运行时环境发生的错误。
Java的异常处理是通过5个关键字来实现的 try、catch、finally、throw、throws。
声明异常
抛出异常
try/catch 代码块放在异常可能发生的地方。try/catch 代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try {
//可能出错的程序代码
} catch(ExceptionClassName e) {
//catch块
}
catch语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
例如:
import java.util.Scanner;
public class Question1_1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try {
System.out.print("Please input an integer: ");
int num = in.nextInt();
System.out.println("3/" + num + "=" + 3 / num);
} catch (ArithmeticException error) {
System.out.println("A number cannot be divided by zero.");
}
System.out.println("Program finished.");
}
}
运行结果:
# 第一次运行:
Please input an integer: 3
3/3=1
Program finished.
# 第二次运行:
Please input an integer: 0
A number cannot be divided by zero.
Program finished.
# 第三次运行:
Please input an integer: c
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:939)
at java.base/java.util.Scanner.next(Scanner.java:1594)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
at homework0401.Question1_1.main(Question1_1.java:10)
注意
还可以调用异常对象的方法输出异常信息。下表是 Throwable 类的主要方法:
在catch块中,还可以继续向上抛出异常 throw e
。
多重捕获块
一个try块后面跟随多个catch块的情况就叫多重捕获。
try{
//程序代码
}catch(ExceptionClassName1 ExpectionObjectName1){
//程序代码
}catch(ExceptionClassName2 ExpectionObjectName2){
//程序代码
}catch(ExceptionClassName3 ExpectionObjectName3){
//程序代码
}
//……
注意
例如,把上面的例子稍微改动一下:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Question1_2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try {
System.out.print("Please input an integer: ");
int num = in.nextInt();
System.out.println("3/" + num + "=" + 3 / num);
} catch (ArithmeticException e1) {
System.out.println("A number cannot be divided by zero.");
} catch (InputMismatchException e2) {
System.out.println("Not an integer.");
} catch (Exception e3) {
System.out.println("Undefined Exception.");
}
System.out.println("Program finished.");
}
}
运行结果:
# 第一次运行:
Please input an integer: 0
A number cannot be divided by zero.
Program finished.
# 第二次运行:
Please input an integer: c
Not an integer.
Program finished.
在try-catch块后加入finally块,可以确保无论是否发生异常,finally块中的代码总能被执行。
通常在finally中关闭程序块已打开的资源,比如:文件流、释放数据库连接等。
finally 代码块出现在 catch 代码块最后,语法如下:
try{
// 程序代码
}catch(ExceptionClassName1 ExpectionObjectName1){
//程序代码
}catch(ExceptionClassName2 ExpectionObjectName2){
//程序代码
}/*更多的catch块*/
finally{
//finally块
}
finally块中语句不执行的唯一情况:异常处理代码中执行 System.exit(1)
退出Java虚拟机。
注意
只有finally块执行完成之后,才会回来执行try块或者catch块中的return或throw语句,如果finally块中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
例如,上面的例子再做改动:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Question1_3 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try {
System.out.print("Please input an integer: ");
int num = in.nextInt();
System.out.println("3/" + num + "=" + 3 / num);
} catch (ArithmeticException e1) {
System.out.println("A number cannot be divided by zero.");
} catch (InputMismatchException e2) {
System.out.println("Not an integer.");
} catch (Exception e3) {
System.out.println("Undefined Exception.");
} finally {
System.out.println("Program finished.");
}
}
}
运行结果略。
当检查性异常产生时,不一定立刻处理它,可以说明用throws把异常声明出来,让专门负责异常处理的代码来解决。throws关键字放在方法签名的尾部。
也可以使用throw关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
注意抛出运行时异常和检查性异常的区别:
在程序中,可能会遇到任何标准异常类都没有充分的描述清楚的问题,这种情况下可以创建自己的异常类。
可以像下面这样定义自己的异常类:
class MyException extends Exception {
//……
}
只继承Exception类来创建的异常类是检查性异常类。一个异常类和其它任何类一样,包含有变量和方法。
习惯上,定义的类应该包含2个构造方法:一个是默认构造方法,另一个是带有详细信息的构造方法。
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。Thinking in Java中这样说:可以将一个类的定义放在另外的一个类的定义中,这就是一个内部类。
如果我们定义的一个内部类需要多次使用,那肯定要给他一个名字;但是如果我们定义一个内部类就唯一使用一次,仅仅在当前位置使用一下,那其实他可以连名字都没有,这就是匿名内部类。在Java里面提供了像这样的定义匿名内部类的方法,匿名内部类在swing事件处理和Android开发中都有广泛的用途。
匿名内部类由于没有名字,所以它的创建方式有点儿奇怪。创建格式如下:
new SuperType(/* construction parameters */) | InterfaceType() {
//匿名内部类的类体部分
}
使用匿名内部类必须要继承一个父类或者实现一个接口,也仅能只继承一个父类或者实现一个接口。由于匿名内部类不能是抽象类,所以它必须要实现它的抽象父类或者接口里面所有的抽象方法。
同时它也没有class关键字,匿名内部类直接使用new来生成隐式的对象的引用。创建匿名内部类时它会立即创建一个该类的实例,同时该类的定义会立即消失,所以匿名内部类是不能够被重复使用。
例如:
public class Parcel {
public Destination destination(String s) { //返回Destination引用
return new Destination() {
//这里用一个匿名类实现了Destination接口,并创建了一个实例引用
private String label = s;
public String readLabel() {
return label;
}
};
}
public static void main(String[] args) {
Parcel parcel = new Parcel();
Destination d = parcel.destination("Tasmania");
}
}
注意
public class Parcel {
public Destination destination(String s, float price) {
return new Destination() {
private int cost;
{ //实例初始化块,相当于构造方法
cost = Math.round(price);
if(cost > 100)
System.out.println("Over budget!");
}
private String label = s;
public String readLabel() {
return label;
}
};
}
public static void main(String[] args) {
Parcel parcel = new Parcel();
Destination d = parcel.destination("Tasmania", 101.395F);
}
}
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为类似 Outter$1.class
的名字。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
原文链接 1 2 作者:Holger