Java程序辅导

C C++ Java Python Processing编程在线培训 程序编写 软件开发 视频讲解

客服在线QQ:2653320439 微信:ittutor Email:itutor@qq.com
wx: cjtutor
QQ: 2653320439
Advances in Programming Languages:
Introduction
Stephen Gilmore
The University of Edinburgh
January 15, 2007
Introduction
Programming languages are indispensible tools in computer science. Computer programs must
be expressed in a formal language for machine execution. Without programming languages we
would not have computer programs.
The nature and form of programming languages is a subject of study in its own right.
Computer scientists have sought to describe formally the syntax, static and dynamic semantics
of programming languages.
Programming language families
It is widely understood that programming languages occur in families with collections of lan-
guages having similar features and properties (C-like languages, Algol-like languages, ML-like
languages, Java-like languages and such).
Is there then any more to programming language design than noticing these family resem-
blances and chosing a family which appeals in some way?
My belief is that there is something more and this lecture course sets out to explain what
it is and to say where programming language design appears to be going.
Approaches to language design
The designers of programming languages set out with objectives such as the following.
To design a secure programming language; to design a reliable language; to design a compact
programming language; to design a useful language; to design a language which is easy to learn.
Sometimes there are other reasons, for example to compete with a rival manufacturer. How-
ever, one thing is certain. No-one sets out to make a rotten programming language which
developers will hate.
Why language design is important
Most students of computer science and software engineering will never design a programming
language. Most practising computer scientists never will either. So why is programming lan-
guage design important and why should we study advances in programming languages? There
are many reasons, some of which are these.
• By learning about programming language design we learn to use language constructs and
features well, working with the grain of the language instead of against it. This means
that we can produce programs which other developers can more easily understand, which
1
UG4 Advances in Programming Languages — 2005/2006 2
can be compiled well by the language compiler, and are frequently more efficient and more
reliable.
• By learning about advances in programming languages we equip ourselves for learning the
programming languages of tomorrow. Computing technology is a fast-moving field. It is
essential to keep learning new skills and new technologies.
The plain truth is that some programming languages are more helpful than others. We can
learn from the design of programming languages which are helpful but we can also learn from
the design of programming languages which are unhelpful. This course discusses both kinds of
language. Most software developers need to use both kinds.
Concretely, high-level languages such as Java are viewed as being a technological improve-
ment on simpler, low-level languages such as C. The reason for this is chiefly that there are
fewer ways in which a Java program can fail than one written in C.
Ways in which C programs can fail
The C program below contains (deliberate) errors but is still passed by the C compiler. (gcc
-Wall generates one warning.)
/* File: programs/c/Initialisation.c */
/* Include standard output library */
#include "stdio.h"
int main () {
int x;
x++;
printf("%d\n", x);
}
This program contains an uninitialised variable, x. The value which it prints is arbitrary. The
end of the main function is reached without returning a value. I compiled the above program
with a recent version of GCC.
[beetgreens]stg: gcc --version
gcc (GCC) 4.1.1 20060525 (Red Hat 4.1.1-1)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The warning produced by gcc is below.
[beetgreens]stg: gcc -Wall Initialisation.c
Initialisation.c: In function ‘main’:
Initialisation.c:9: warning: control reaches end of non-void function
Note that this is just a warning. The program has been compiled to an executable which can
be run. The default behaviour of the C compiler is to compile with very few optimisations.
Asking for optimisations to be enabled requires the C compiler to perform more static analysis
and so may generate additional warnings.
[beetgreens]stg: gcc -Wall -O2 Initialisation.c
Initialisation.c: In function ’main’:
UG4 Advances in Programming Languages — 2005/2006 3
Initialisation.c:9: warning: control reaches end of non-void function
Initialisation.c:7: warning: ’x’ is used uninitialized in this function
The equivalent program in Java is below.
/* File: programs/java/Initialisation.java */
class Initialisation {
public static void main (String[] args) {
int x;
x++;
System.out.println(x);
}
}
This is faulted by the compiler with the error variable x might not have been initialized.
Uninitialised variables in some languages complicate parameter passing. Is the following
program legal in Java?
/* File: programs/java/Initialisation2.java */
class Initialisation2 {
static void assign (int x) {
x = 0;
}
public static void main (String[] args) {
int x;
assign(x);
x++;
System.out.println(x);
}
}
Again, this is faulted by the compiler with the same error. Java calls by value, so a variable
such as x should hold a value at the point of the call to the method assign(). Static analysis
in the compiler determines that it does not (or might not, in general) so the program is faulted
by the compiler.
This program differs in that it moves the declaration and use of the variable into an instance
method of the class.
/* File: programs/java/Initialisation3.java */
class Initialisation3 {
void init () {
int x;
x++;
System.out.println(x);
}
public static void main (String[] args) {
Initialisation3 i = new Initialisation3();
i.init();
}
}
This program is not different from the previous ones. The variable x is still not being given a
value before use. The program is still faulted by the compiler.
UG4 Advances in Programming Languages — 2005/2006 4
Now we move the declaration of the variable out of the method body and into the class
itself.
/* File: programs/java/Initialisation4.java */
class Initialisation4 {
int x;
void init () {
x++;
System.out.println(x);
}
public static void main (String[] args) {
Initialisation4 i = new Initialisation4();
i.init();
}
}
Moving the variable from the method to the class materially changes its category — it is now
an instance variable — and Java will give this int variable the default initial value of 0. This
program compiles and executes successfully, producing the expected output (“1”).
Definite assignment
The Java programming language introduced the concept of definite assignment—each variable
must be defined on all paths which lead to a use of that variable. We would point to this being
an advance in programming language design.
A different approach is taken in functional programming languages, which do not operate
on updateable variables. Pure functional languages do not offer the capability to update store
in any way but even impure functional languages offer this capability only in a restricted form.
Enforced initialisation
Functional languages such as Caml support references instead of variables. The difference
is essentially that initialisation of reference values is forced by the syntax of the language.
It is not possible to separate declaration from initialisation and in that sense, these are not
variables (because it is possible to do that with variables in traditional imperative programming
languages).
(* File: programs/caml/Initialisation.ml *)
(* main function definition *)
let main () =
let x = ref 0 in (* initialisation *)
x := !x + 1; (* assignment *)
print_int (!x); (* dereference *)
exit 0;;
(* run main function *)
main ();;
Scripting languages
Scripting languages such as Ruby mostly do not require declaration of variables at all. Thus a
use of an unassigned variable manifests itself as a run-time type error.
UG4 Advances in Programming Languages — 2005/2006 5
# File: programs/ruby/Initialisation.rb
x = x + 1
puts x
Ruby is an interpreted language without a separate compilation phase so type errors in Ruby
programs are detected at run-time. Ruby is a dynamically typed language. The run-time error
is reported thus.
[beetgreens]stg: ruby Initialisation.rb
Initialisation.rb:1: undefined method ‘+’ for
nil:NilClass (NoMethodError)
Summary
Uninitialised variables represent uncertainty about the behaviour of programs, and complicate
reasoning about parameter passing.
• In C there are no guarantees that variables have been initialised. In Ruby none that they
have been declared.
• In Caml updateable memory must be initialised, but at the point of declaration, which
might sometimes be inconvenient in a strongly-typed language.
• In Java one can separate declaration from initialisation and the definite assignment rule
guarantees that every variable will be initialised before it is used.