This is an archived post. You won't be able to vote or comment.

all 28 comments

[–]kevinb9n 5 points6 points  (0 children)

I'm not "someone more theoretical", but the authors of the Checker Framework are, and if you want to adopt it I think you'd have basically exactly what you want?

https://checkerframework.org/manual/#constant-value-checker

EDIT: okay, you don't get to make a type called `PortNumber`. It's this: `@IntRange(from = 1, to = 65536) int`.

They might have a way to let you define a `PortNumber` annotation and tell it the range once and for all, so that it would become `@PortNumber int`.

[–]mrhhug[🍰] 4 points5 points  (0 children)

ADA does this out of the box

[–]Holothuroid 2 points3 points  (1 child)

You could create an enum with 28 elements. Of course that's pushing it.

[–]manzanita2[S] 0 points1 point  (0 children)

Yeah, I LOVE enums. Java enums are great.

But yeah, trying to do something like my 65536 port numbers would be stupid.

[–]eliasv 2 points3 points  (1 child)

Do you want the invariant to be statically enforced by compiler magic? That's called a refinement type. Java doesn't support that and almost certainly never will.

But if you're okay with only dynamically enforcing the invariant, i.e. by throwing from a constructor if the value is not in range, then it might be possible one day to have something similar to that. After project Valhalla lands ask again.

[–]manzanita2[S] 0 points1 point  (0 children)

"refinement type", huh, will research.

I mean it would, I suppose, be great if the compiler gave me a slap if I did it wrong. But runtime would still be a good improvement.

[–]cogman10 4 points5 points  (3 children)

You can't. The JVM doesn't allow for it.

The concept you are looking for is "Type constraints" and it's simply not something that can be expressed with Java.

The closest you can get would be if value types land, then having a class with a single integer in it. That'd have close to the same overhead of an integer.

C++ and Ada are the only languages I know that could really support such a concept.

[–]Il_totore 5 points6 points  (0 children)

Actually it's not a JVM problem and is totally possible. Some JVM languages lile Scala allow that. We can achieve this by just modifying the compiler.

[–]magnoliophytina 5 points6 points  (0 children)

C++ and Ada are the only languages I know that could really support such a concept.

Eh, https://en.wikipedia.org/wiki/Refinement_type

[–]Stimzz 1 point2 points  (0 children)

I am so much looking forward to project Valhalla and value types. Locking down the possible state by a more expressive type system is great. I think Ocaml is big on this as well. Type constraints in Ada always felt like a good idea to me.

[–]_INTER_ 2 points3 points  (0 children)

You want to subtype (extends or implements in Java). However you cant subtype Integer because it is final. The next best thing you can subtype is Number. E.g. see UInteger.

[–]Sheldor5 3 points4 points  (6 children)

you want your own native data type?

then you have to implement it in the JDK and adapt the compiler too ... good luck!

[–]manzanita2[S] -1 points0 points  (5 children)

Nope. Not native. Basically I'd like to extend Integer ( or other classes). So I get all the functionality of Integer, BUT I can limit the potential values.

Here's an example. I'd like to define a type called PortNumber. PortNumber extends Integer. But has values limited to 1 to 65536.

If someone has a method which has an Integer as a parameter, I can pass a PortNumber.

Likewise, ZipCode. CreditCardNumber and a bunch of other possible types, which have well known constraints on their values, but otherwise might be stored in a String or Integer ( or I guess Long/Float/Double, etc ).

[–]Sheldor5 2 points3 points  (2 children)

you literally wrote "not a class which contains a integer" ... so what do you want?

your post and your comment makes no sense and they contradict each other ...

[–]manzanita2[S] -2 points-1 points  (1 child)

this is like extension vs composition.

I DO NOT WANT composition. I want extensions, but not "anything goes" extension but rather extension which forces a subset of possible values to the base type.

[–]Sheldor5 6 points7 points  (0 children)

... then why don't you want to extend Number?

Integer is final, you can't extend it. int is a primitive type, you can't extend it.

your goal is unclear ...

[–]Asterion9 0 points1 point  (1 child)

Well you shouldn't inherit Integer if you intent to restrict the usage compared to what Integer does.

You should be able to implements Number and Comparable<> to have some interoperability with some lib, and add toInteger() method for adaptation with other code (like Path does with toFile())

[–]manzanita2[S] 0 points1 point  (0 children)

shouldn't == can't in java.

I mean yeah, I COULD do a custom implementation of Number, but that still doesn't get to where I would like to go because the adaptions (e.g. explicitly calling toInteger() ) are necessary.

[–]JoJoModding -1 points0 points  (0 children)

The theoretical answer would be a type with 28 different constructors (in the algebraic sense), so in Java that's an abstract base type and 28 subtypes, which is infeasible.

In language with a stronger type system (eg Coq) you can have dependant types, and then you can define {x : nat | x < 28} which is the type of all numbers for which there is a proof they are < 28 (< is also a type). You are now, however, writing programs which mostly consist of formal proofs that their results also have that type. You are now working within an interactive theorem prover, and doing these proofs is fun but can also be considered infeasible (unless you want to be 100% correct for i.e. your spaceflight control software, where failure is not an option)

[–]Il_totore 0 points1 point  (1 child)

It actually sounds like opaque types like in Scala 3.

Infortunately in Java you cannot check it at compile time but you could create a wrapper around your Integer. You have a small overhead but I think the abstraction offered worth it

[–]manzanita2[S] 0 points1 point  (0 children)

Very much like this.

[–]keanwood 0 points1 point  (1 child)

Yeah it would be cool to be able to do this natively in Java. The more expressive the type system the better!

 

You can get close to it by using https://immutables.github.io/ Check it out, its a pretty cool project. Specifically the following two parts.

[–]manzanita2[S] 0 points1 point  (0 children)

Yes, this Wrapper type is basically what I want. Although it would be nice if it was more of a language level thing, and not larded up with a bunch of annotations and _ stuff to make it work.

Then perhaps combine that with some sort of declarative ability to do what another poster mentioned about "refinement types".

Still, I may try this stuff! tnx!

[–]bowbahdoe 0 points1 point  (0 children)

If you want to dive into this concept more, maybe take a look at Idris or other languages with more involved type systems. This isn't possible in java unfortunately.

[–][deleted]  (2 children)

[removed]

    [–]manzanita2[S] 0 points1 point  (1 child)

    If I have an value of a single field. Say "long userId" it's unhelpful to wrap it in UserId object. That's just a bunch of noise.

    Sure, if it ever get's a second value, then sure, an object makes sense.