Static/Dynamic vs Strong/Weak
Static/Dynamic Typing is about when type information is acquired (Either at compile time or at runtime)
Strong/Weak Typing is about how strictly types are distinguished (e.g. whether the language tries to do an implicit conversion from strings to numbers).
See the wiki-page for more detailed information.
You have discovered a soft spot in the terminology that amateurs use to talk about programming languages. Don't use the terms "strong" and "weak" typing, because they don't have a universally agreed on technical meaning. By contrast, static typing means that programs are checked before being executed, and a program might be rejected before it starts. Dynamic typing means that the types of values are checked during execution, and a poorly typed operation might cause the program to halt or otherwise signal an error at run time. A primary reason for static typing is to rule out programs that might have such "dynamic type errors".
Strong typing generally means that there are no loopholes in the type system, whereas weak typing means the type system can be subverted (invalidating any guarantees). The terms are often used incorrectly to mean static and dynamic typing. To see the difference, think of C: the language is type-checked at compile time (static typing), but there are plenty of loopholes; you can pretty much cast a value of any type to another type of the same size---in particular, you can cast pointer types freely. Pascal was a language that was intended to be strongly typed but famously had an unforeseen loophole: a variant record with no tag.
Implementations of strongly typed languages often acquire loopholes over time, usually so that part of the run-time system can be implemented in the high-level language. For example, Objective Caml has a function called Obj.magic
which has the run-time effect of simply returning its argument, but at compile time it converts a value of any type to one of any other type. My favorite example is Modula-3, whose designers called their type-casting construct LOOPHOLE
.
Having said that, you can't count on any two people using the words "strong" and "weak" in exactly the same way. So avoid them.
Simply put it this way: in a statically typed language the type is static, meaning once you set a variable to a type, you CANNOT change it. That is because typing is associated with the variable rather than the value it refers to.
For example in Java:
String str = "Hello"; //statically typed as string
str = 5; //would throw an error since java is statically typed
Whereas in a dynamically typed language the type is dynamic, meaning after you set a variable to a type, you CAN change it. That is because typing is associated with the value rather than the variable.
For example in Python:
str = "Hello" # it is a string
str = 5 # now it is an integer; perfectly OK
On the other hand, the strong/weak typing in a language is related to implicit type conversions (partly taken from @Dario's answer):
For example in Python:
str = 5 + "hello"
# would throw an error since it does not want to cast one type to the other implicitly.
whereas in PHP:
$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0
// PHP is weakly typed, thus is a very forgiving language.
Static typing allows for checking type correctness at compile time. Statically typed languages are usually compiled, and dynamically typed languages are interpreted. Therefore, dynamicly typed languages can check typing at run time.
Weak typing means that the type of an object can change depending on context. For example in a weakly typed language the string "123" may be treated as the number 123 if you add another number to it. Examples of languages with weak typing are bash, awk and PHP.
Another kind of weakly typed language is C, where the data at a memory address can be treated as a different type by casting.
In a strongly typed language the type of an object does not change - an int is always an int and trying to use it as a string will result in an error. Both Java and Python are strongly typed.
The difference between dynamic and static typing is when the type rules are enforced. In a statically typed language the type of every variable and parameter must be declared in the source and is enforced at compile time. In a dynamically typed language the types are only checked when they are used at runtime. So Java is statically typed and Python is dynamically typed.
However the boundaries can be a little blurry at times. For example although Java is statically typed, every time you use reflection or a cast (e.g. when using containers of Objects) they you are deferring the type check to runtime.
Similarly most strongly typed languages will still automatically convert between integers and floats (and in some languages abitrary precision BigInts).
Today researching about this subject I came across this great article http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html It cleared up a lot of things for me and I thought It may add to some of the great answers above.
Strong and Weak Typing:
Probably the most common way type systems are classified is "strong" or "weak." This is unfortunate, since these words have nearly no meaning at all. It is, to a limited extent, possible to compare two languages with very similar type systems, and designate one as having the stronger of those two systems. Beyond that, the words mean nothing at all.
Static and Dynamic Types
This is very nearly the only common classification of type systems that has real meaning. As a matter of fact, it's significance is frequently under-estimated [...] Dynamic and static type systems are two completely different things, whose goals happen to partially overlap.
A static type system is a mechanism by which a compiler examines source code and assigns labels (called "types") to pieces of the syntax, and then uses them to infer something about the program's behavior. A dynamic type system is a mechanism by which a compiler generates code to keep track of the sort of data (coincidentally, also called its "type") used by the program. The use of the same word "type" in each of these two systems is, of course, not really entirely coincidental; yet it is best understood as having a sort of weak historical significance. Great confusion results from trying to find a world view in which "type" really means the same thing in both systems. It doesn't.
Explicit/Implicit Types:
When these terms are used, they refer to the extent to which a compiler will reason about the static types of parts of a program. All programming languages have some form of reasoning about types. Some have more than others. ML and Haskell have implicit types, in that no (or very few, depending on the language and extensions in use) type declarations are needed. Java and Ada have very explicit types, and one is constantly declaring the types of things. All of the above have (relatively, compared to C and C++, for example) strong static type systems.