Dynamic typing in java

Dynamic Generic Typing in Java

Java generics are a compile time feature, not a run time feature.

Here is a link to the Java generics Tutorial.

This can never work with Java:

You must either use polymorphism (say, each object implements a known interface) or RTTI (instanceof or Class.isAssignableFrom()).

 class Record < public Record(String blah) < . >public Record(Integer blah) < . >. other constructors. > 

or you might use the Builder pattern.

Creating instances from Generic Types at Runtime

I am not entirely sure what you are trying to accomplish, but at a first glance it looks like the simplest solution is the best solution.

It could be solved with using a scripting environment ( Groovy, JavaScript, JRuby, Jython ) that could dynamically evaluate and execute arbitrary code to create the objects, but that got extremely convoluted and overly complex, just to create an object.

But unfortunately I think it has a very pedestrian solution.

As long as there is a predefined set of supported types, you can use a Factory pattern. Here I just leverage the Provider<>T interface from the javax.inject / com.google.inject package.

Q26289147_ProviderPattern.java

public class Q26289147_ProviderPattern < private static final ListCLASS_NAMES = ImmutableList.of("String", "Integer", "Boolean"); private static final Map> PROVIDERS; static < final ImmutableMap.Builder> imb = ImmutableMap.builder(); for (final String cn : CLASS_NAMES) < switch (cn) < case "String": imb.put(cn, new Provider() < @Override public StrawManParameterizedClassget() < return new StrawManParameterizedClass() <>; > >); break; case "Integer": imb.put(cn, new Provider() < @Override public StrawManParameterizedClassget() < return new StrawManParameterizedClass() <>; > >); break; case "Boolean": imb.put(cn, new Provider() < @Override public StrawManParameterizedClassget() < return new StrawManParameterizedClass() <>; > >); break; default: throw new IllegalArgumentException(String.format("%s is not a supported type %s", cn, Joiner.on(",").join(CLASS_NAMES))); > > PROVIDERS = imb.build(); > static void read(@Nonnull final StrawManParameterizedClass smpc) < System.out.println(smpc.type.toString()); >static abstract class StrawManParameterizedClass  < final TypeTokentype = new TypeToken(getClass()) <>; @Override public String toString() < return type.getRawType().getCanonicalName(); >> public static void main(final String[] args) < for (final String cn : CLASS_NAMES) < read(PROVIDERS.get(cn).get()); >> > 

Disclaimer:

This is just a proof of concept example, I would never use a switch statement like that in production code I would use a Strategy Pattern or Chain of Responsibility Pattern to encapsulate the logic of what type to create based on the ClassName key.

This initially looked like a generics problem, it isn’t, it is a creation problem.

That said, you don’t need to pass around instances of Class you can get Generic Type information off of Parameterized classes at runtime with TypeToken from Guava.

You can even create instances of any generic type at runtime with TypeToken from the Guava library.

The main problem is this syntax isn’t supported: Geography geo; and I can’t think of anyway to fake it other than the Provider implementation above.

Here is a straw man example of how to use TypeToken so that your parameterized classes will always know their types!

Q26289147.java

import com.google.common.reflect.TypeToken; public class Q26289147 < public static void main(final String[] args) throws IllegalAccessException, InstantiationException < final StrawManParameterizedClasssmpc = new StrawManParameterizedClass() <>; final String string = (String) smpc.type.getRawType().newInstance(); System.out.format("string = \"%s\"",string); > static abstract class StrawManParameterizedClass  < final TypeTokentype = new TypeToken(getClass()) <>; > > 

Notes:

  1. Works great for classes that have a default no arg constructor.
  2. Works better than using straight reflection if there are no default no arg constructors.
  3. Should play well with Guice allowing you to use the .getRawType() generated Class to pass to getInstance() of an Injector. have not tried this yet, I just thought of it!
  4. You can use Class.cast() to do casting that doesn’t need @SuppressWarning(«unchecked») all over the place.

If you don’t know the type, you cannot enforce compile time checks with generics.

Just for the sake of using it you could say

Источник

2.1. Data Types¶

In a dynamically typed programming language (like JavaScript or Python), a variable or parameter can refer to a value of any data type (string, number, object, etc.) at any time. When the variable is used, the interpreter figures out what type it is and behaves accordingly.

Java is a statically typed language. When a variable or parameter is declared in a statically typed language, the data type for the value must be specified. Once the declaration is made, the variable or parameter cannot refer to a value of any other type.

For example, this is legal in JavaScript, a dynamically typed language:

let dynamicVariable = "dog"; console.log(typeof(dynamicVariable)); dynamicVariable = 42; console.log(typeof(dynamicVariable)); 

After line 1 executes, dynamicVariable holds a string data type. After line 3 runs, dynamicVariable becomes a number type. dynamicVariable is allowed to hold values of different types, which can be reassigned as needed when the program runs.

However, the corresponding code in Java will result in a compiler error:

String staticVariable = "dog"; staticVariable = 42; 
error: incompatible types: int cannot be converted to String

The compiler error occurs when we try to assign 42 to a variable of type String .

Take-home lesson: We must declare the type of every variable and parameter in a statically typed language. This is done by declaring the data type for the variable or parameter BEFORE its name, as we did in the example above: String staticVariable = «dog» .

We only need to specify the type of a variable or parameter when declaring it. Further use of the variable or parameter does not require us to identify its type. Doing so will result in an error.

Dynamic and static typing are examples of different type systems . The type system of a programming language is one of the most important high-level characteristics that programmers use when discussing the differences between languages. Here are a few examples of popular languages falling into these two categories:

  1. Dynamic: Python, Ruby, Javascript, PHP
  2. Static: Java, C, C++, C#, TypeScript

Because we need to give plenty of attention to types when writing Java code, let’s begin by exploring the most common data types in this language.

2.1.2. Strings and Single Characters¶

2.1.2.1. Immutability¶

Strings in Java are immutable, which means that the characters within a string cannot be changed.

2.1.2.2. Single vs. Double Quotation Marks¶

Java syntax requires double quotation marks when declaring strings.

Java has another variable type, char , which is used for a single character. char uses single quotation marks. The single character can be a letter, digit, punctuation, or whitespace like tab ( ‘\t’ ).

String staticVariable = "dog"; char charVariable = 'd'; 

2.1.2.3. Manipulation¶

The table below summarizes some of the most common string methods available in Java. For these examples, we use the string variable String str = «Rutabaga» .

Returns the character at index 3, ( ‘a’ ).

Returns the characters from indexes 2 — 4, ( «tab» ).

Returns the length of the string.

Returns the index for the first occurrence of ‘a’, ( 3 ).

Splits the string into sections at each delimiter and stores the sections as elements in an array.

In Java, concat concatenates only two strings. To join multiple strings, method chaining is required.

Removes any whitespace at the beginning or end of the string.

Changes all alphabetic characters in the string to UPPERCASE or lowercase, respectively.

Searches for the specified text within a string and returns true or false .

Compares strings for equality and returns a boolean.

We will explore the differences between using == and .equals() when we discuss Java operators. For now, use .equals() if you need to compare two strings.

2.1.3. Primitive Types¶

A primitive data type is a basic building block. Using primitive data types, we can build more complex data structures called object data types.

Java uses its own a set of primitive data types. The table below shows the most common types that beginners are likely to encounter. A more complete list can be found on the Oracle website .

Java Primitive Data Types ¶

Represents positive and negative whole numbers.

3.141593 and 1234.567 and 2.0

Represents positive and negative decimal numbers with up to 7 digits.

3.14159265358979 and 10000.12345678912

Represents positive and negative decimal numbers with 15-16 digits.

A single unicode character enclosed in single quotes » .

Booleans in Java are NOT capitalized.

As we will see in a later section, the float data type sacrifices some accuracy for speed of calculation. Thus, evaluating 1.11111 + 3 results in an answer of 4.1111097 instead of 4.11111.

Anytime you need to perform calculations with decimal values, consider using the double type instead of float .

2.1.4. Non-primitive Types¶

Primitive data types are immutable and can be combined to build larger data structures. One example is forming the String “LaunchCode” from multiple char characters (‘L’, ‘a’, ‘u’, etc.).

String is a non-primitive data type, also called an object type. As we saw in the String table above, object types have methods which we can call using dot notation. Primitive data types do not have methods.

Primitive data types in Java begin with a lower case letter, while object data types in Java begin with a capital letter.

Later in this chapter, we will explore the Array and Class object types.

2.1.5. Autoboxing¶

There may be situations when we call a method that expects an object as an argument, but we pass it a primitive type instead (or vice versa). In these cases, we need to convert the primitive type to an object, or convert an object type into a primitive.

In older versions of Java, it was the programmer’s responsibility to convert back and forth between primitive types and object types whenever necessary. Converting from a primitive type to an object type was called boxing, and the reverse process (object to primitive) was called unboxing.

int someInteger = 5; Integer someIntegerObject = Integer.valueOf(someInteger); ClassName.methodName(someIntegerObject); 
  1. Line 1 declares and initializes the variable someInteger .
  2. Line 2 converts the primitive int to the Integer object type.
  3. Line 3 calls methodName and passes someIntegerObject as the argument. If methodName expects an object type and we tried sending an int instead, we would generate an error message.

Let’s assume that a method returns a random number of Integer type, and we want to combine it with a value of int type.

int ourNumber = 5; Integer randomNumber = ClassName.randomNumberGenerator(); int randomInt = (int) randomNumber; int sum = ourNumber + randomInt; 
  1. Line 2 declares and initializes randomNumber as an Integer type.
  2. Line 3 converts randomNumber to an int and stores the value in the randomInt variable.

Converting between data types in order to pass values between methods quickly became tedious and error prone. In the newer versions of Java, the compiler is smart enough to know when to convert back and forth, and this is called autoboxing.

For us, the consequence of autoboxing is that in many situations, we can use primitive and object types interchangeably when calling methods or returning data from those methods.

It’s a best practice to use primitives whenever possible. The primary exception to this occurs when storing values in collections, which we’ll learn about in a future lesson.

Each of the primitive data types has a corresponding object type:

  1. int —> Integer
  2. float —> Float
  3. double —> Double
  4. char —> Character
  5. boolean —> Boolean

2.1.6. References¶

2.1.7. Check Your Understanding¶

Which of the following is NOT a number data type in Java:

Name the Java method responsible for checking string equality:

Источник

Читайте также:  Upgrading python on centos
Оцените статью